天道酬勤,学无止境

Monad 转换器:使用 MaybeT(状态堆栈)实现堆栈机(Monad transformers: Implementation of a stack machine with MaybeT (State Stack))

问题

我正在尝试实现一个 Maybe-State monad 转换器并用它来实现一个简单的堆栈机。 state monad 的定义也许应该是正确的。 现在我正在尝试实现流行:

pop :: MaybeT (State Stack) Int

因此,如果堆栈为空,则不返回任何内容,否则返回Just <popped stack> 。 这是我到目前为止:

pop :: MaybeT (State Stack) Int
pop = guard True (do (r:rs) <- get
                     put rs
                     return r)

(显然True只是一个虚拟占位符 - 我稍后会实现该条件,现在我想让另一部分正确)。

我的代码有什么问题? 根据我的理解, guard需要一个条件( True )和一个函数 f。 如果条件为真,则给出pure f

就我而言,

pure = MaybeT . return . Just

那么我的函数 f 不应该只返回一个State Stack Int吗?


这是完整的代码,以及我对MaybeTState

import Control.Applicative (Alternative(..))
import Control.Monad (liftM, ap, guard)
import Control.Monad.Trans.Class (MonadTrans(lift))

main :: IO()
main = return ()


-- State Monad
--------------

newtype State s a = MakeState { runState :: s -> (a, s) }

instance Functor (State s) where
    fmap  = liftM


instance Applicative (State s) where
    pure a = MakeState $ \s -> (a, s)
    (<*>)  = ap

instance Monad (State s) where
    return a = MakeState $ \s -> (a, s)
    m >>= k  = MakeState $ \s -> let (x, s') = runState m s
                              in runState (k x) s'

get :: State s s
get = MakeState $ \s -> (s, s)

put :: s -> State s ()
put s = MakeState $ \_ -> ((), s)

modify :: (s -> s) -> State s ()
modify f = MakeState $ \s -> ((), f s)

-- MaybeT MonadTransformer
---------------------------

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }

instance Monad m => Functor (MaybeT m) where
    fmap a x = MaybeT $ do e <- runMaybeT x
                           return $ fmap a e



instance Monad m => Applicative (MaybeT m) where
    pure      = MaybeT . return . Just
    (<*>) a b = MaybeT $ do e <- runMaybeT a
                            f <- runMaybeT b
                            return $ e <*> f

instance Monad m => Monad (MaybeT m) where
    return  = pure
    a >>= b = MaybeT $ do aa <- runMaybeT a
                          maybe (return Nothing) (runMaybeT . b) aa


instance Monad m => Alternative (MaybeT m) where
  empty   = MaybeT $ return Nothing
  a <|> b = MaybeT $ do aa <- runMaybeT a
                        bb <- runMaybeT b
                        return $ aa <|> bb


instance MonadTrans MaybeT where
    -- "herwrappen" van het argument
    lift x = MaybeT $ do r <- x
                         return $ Just r


-- Stack Manipulation
---------------------

type Stack = [Int]

-- plaats het argument bovenop de stack
push :: Int -> State Stack ()
push x = do r <- get
            put (x:r)
-- geef de grootte van de stack terug
size :: State Stack Int
size = do r <- get
          return $ length r

-- neem het eerste element van de stack, als het aanwezig is
-- (hint: hoogle naar `guard`)
pop :: MaybeT (State Stack) Int
pop = guard (True) (do (r:rs) <- get
                       put rs
                       return r)
回答1

guard不需要两个参数,它只需要一个Bool参数。

您还需要将您的状态操作提升到MaybeT

pop :: MaybeT (State Stack) Int
pop = do
  guard True
  (r:rs) <- lift get
  lift $ put rs
  return r
回答2

首先,您应该了解如果您的堆栈为空,您的模式r:rs <- get失败。 但是你把它写在 do-block 中,所以会调用fail函数。 它是为Monad m => MaybeT m实现的,如下所示: fail _ = MaybeT (return Nothing) 。 这意味着如果模式失败,它将返回Nothing 。 那就是你想要的。

所以,你可以这样做:

pop :: MaybeT (State Stack) Int
pop = do r:rs <- get
         put rs
         return r
回答3

为了比较起见,这里有一个更粗略的实现,它既不依赖于guard也不依赖于fail

pop :: MaybeT (State Stack) Int
pop = do
  stk <- lift get
  case stk of
    [] -> empty
    (r:rs) -> do
      lift (put rs)
      return r

当堆栈为[]时产生empty等同于以您想要的方式使用guard或使用fail来利用失败的模式匹配(如自由泳的答案)。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • IO + Maybe最简单的“傻瓜” monad变压器示例(Simplest non-trivial monad transformer example for “dummies”, IO+Maybe)
    问题 有人可以举一个非常简单的(很少的行数)monad转换器示例,这是不平凡的(即,不使用Identity monad,据我所知)。 例如,某人将如何创建一个可以执行IO并且可以处理故障的monad(也许)? 证明这一点的最简单的例子是什么? 我浏览了一些monad转换器教程,它们似乎都使用State Monad或Parsers或一些复杂的东西(对于newbee)。 我希望看到比这更简单的东西。 我认为IO +也许会很简单,但我真的不知道该怎么做。 我如何使用IO + Maybe monad堆栈? 最重要的是什么? 到底会是什么? 为什么? 在哪种用例中,您想使用IO + Maybe monad还是Maybe + IO monad? 完全创建这样的复合monad是否有意义? 如果是,什么时候,为什么? 回答1 该文件可在此处作为.lhs文件使用。 MaybeT转换器将使我们能够突破单MaybeT计算,就像抛出异常一样。 首先,我将快速介绍一些预备知识。 跳至“向IO添加Maybe权力”示例。 首先是一些进口: import Control.Monad import Control.Monad.Trans import Control.Monad.Trans.Maybe 经验法则: 在monad堆栈中,IO始终位于底部。 通常,其他类似IO的monad也总是出现在底部
  • 如何设计单子堆栈?(How to design a monadic stack?)
    问题 您如何设计和构建单子堆栈? 第一次,我需要构建一个单子堆栈(使用变压器)来解决现实世界中的问题,但是我不确定要以哪种顺序堆叠变压器。 如您所知,只要计算具有种类* -> * ,基本上任何东西都可以在变换器中扮演内部monad的角色,因此有两个问题: 某个特定的变压器是否应该位于堆栈的顶部(例如ReaderT?WriterT?) 是什么驱动设计? 直觉? 类型? (例如,根据您的API的需要调整堆栈的形状) 每个堆栈都是同构的(在一定程度上),还是如果我不正确地构建堆栈,我可能最终会导致无法使用某些底层的monad或产生大量的mess肿的lift . lift . liftIO [...] lift . lift . liftIO [...] lift . lift . liftIO [...] ? 我的直觉表明,如果转换器派生某些实例(例如,MonadReader,MonadIO等,就像mtl大多数转换器一样),则将转换器放置的顺序无关紧要。 我很想听听经验丰富的Haskellers提供的有关最佳做法或经验法则的信息。 forever $ print "Thanks!" 一种。 回答1 这需要经验。 要记住的一件事是,单声道转换器对转换的单声道一无所知,因此外部转换器受内部转换器的行为“束缚”。 所以 StateT s (ListT m) a 首先,由于内部monad
  • 在 State Monad 中构建关于错误处理的最小 Haskell 示例(Constructing minimal Haskell example on error-handling in the State Monad)
    问题 我正在绞尽脑汁,试图了解如何将State monad 与Maybe结合起来。 让我们从一个具体的(并且有意为琐碎/不必要的)示例开始,在该示例中,我们使用State monad 来查找数字列表的总和: import Control.Monad.State list :: [Int] list = [1,4,5,6,7,0,3,2,1] adder :: Int adder = evalState addState list addState :: State [Int] Int addState = do ms <- get case ms of [] -> return 0 (x:xs) -> put xs >> fmap (+x) addState 凉爽的。 现在让我们修改它,使其在列表包含数字0时返回Nothing 。 换句话说, evalState addState' list应该返回Nothing (因为list包含0 )。 我以为它可能看起来像这样...... addState' :: State [Int] (Maybe Int) addState' = do ms <- get case ms of [] -> return (Just 0) (0:xs) -> return Nothing (x:xs) -> put xs >> fmap (fmap (+x
  • Haskell:lift 与liftIO(Haskell: lift vs liftIO)
    问题 什么情况下应该使用liftIO ? 当我使用ErrorT String IO , lift函数可以将 IO 操作提升到ErrorT ,因此liftIO似乎是多余的。 回答1 lift总是从“上一个”层lift 。 如果您需要从第二层提升,则需要lift . lift lift . lift等。 另一方面, liftIO总是从 IO 层提升(当存在时,它总是在堆栈的底部)。 所以,如果你有超过 2 层的 monad,你会喜欢liftIO 。 比较以下 lambda 表达式中参数的类型: type T = ReaderT Int (WriterT String IO) Bool > :t \x -> (lift x :: T) \x -> (lift x :: T) :: WriterT String IO Bool -> T > :t \x -> (liftIO x :: T) \x -> (liftIO x :: T) :: IO Bool -> T 回答2 LiftIO 只是 IO Monad 的快捷方式,无论您在哪个 Monad 中。基本上,liftIO 等于使用可变数量的电梯。 起初这可能听起来有些多余,但使用liftIO有一个很大的优势:它使您的IO代码独立于实际的Monad构造,因此无论您的最终Monad构建了多少层,您都可以重用相同的代码(这非常重要在编写
  • 目录树的广度优先遍历不是偷懒(breadth-first traversal of directory tree is not lazy)
    问题 我尝试遍历目录树。 朴素的深度优先遍历似乎不会以懒惰的方式生成数据并且会耗尽内存。 我接下来尝试了广度优先的方法,它显示了同样的问题——它使用了所有可用的内存,然后崩溃了。 我的代码是: getFilePathBreadtFirst :: FilePath -> IO [FilePath] getFilePathBreadtFirst fp = do fileinfo <- getInfo fp res :: [FilePath] <- if isReadableDirectory fileinfo then do children <- getChildren fp lower <- mapM getFilePathBreadtFirst children return (children ++ concat lower) else return [fp] -- should only return the files? return res getChildren :: FilePath -> IO [FilePath] getChildren path = do names <- getUsefulContents path let namesfull = map (path </>) names return namesfull testBF fn = do --
  • 有没有人在野外遇到过 Monad Transformer?(Has anyone ever encountered a Monad Transformer in the wild?)
    问题 在我的业务领域 - 金融机构的后台 IT - 软件组件携带全局配置,记录其进度,进行某种错误处理/计算短路是很常见的......事情可以通过 Haskell 中的 Reader-、Writer-、Maybe-monads 等很好地建模,并与 monad 转换器组合在一起。 但是似乎有一些缺点:monad 转换器背后的概念非常棘手且难以理解,monad 转换器导致非常复杂的类型签名,并且它们会造成一些性能损失。 所以我想知道:在处理上面提到的那些常见任务时,monad 转换器是最佳实践吗? 回答1 Haskell 社区在这个问题上存在分歧。 John Hughes 报告说,他发现教授 monad 转换器比教授 monad 更容易,而且他的学生用“转换器优先”的方法做得更好。 GHC 开发人员通常会避免使用 monad 转换器,而是更喜欢将自己的 monad 集成在一起,以集成他们需要的所有功能。 (就在今天,有人毫不含糊地告诉我 GHC不会使用我三天前定义​​的 monad 转换器。) 对我来说,monad 转换器很像无点编程(即没有命名变量的编程),这是有道理的; 毕竟,它们在类型级别完全是无编程点的。 我从不喜欢无点编程,因为能够偶尔引入名称很有用。 我在实践中观察到的是 Hackage 上可用的 monad 转换器的数量非常多,而且大多数都非常简单。
  • 在堆栈项目中添加 MaybeT 依赖时遇到错误(Encountering error while adding MaybeT dependency in stack project)
    问题 我正在使用 HXT 关注本教程 webScraper。 我在这里使用堆栈。 在为 MaybeT 添加依赖项时,它要求: 推荐操作:尝试将以下内容添加到 /Users/***/Haskell Development/Scrapper/stack.yaml 中的 extra-deps: 也许T-0.1.2 现在这样做以在运行堆栈构建时得到以下消息: 在 MayT-0.1.2 的依赖项中: base-4.9.0.0 must match <4.8 (latest 适用的是 4.7.0.2) 由于 Scrapper-0.1.0.0 -> MaybeT-0.1.2 作为 Stack 的新手,我无法解决问题,在我的 cabal 文件中的依赖项: build-depends: base >= 4.7 && < 5 , hxt , url , HTTP , MaybeT 在 stack.yaml 中 resolver: lts-7.12 extra-deps: [MaybeT-0.1.2] 我错过了什么。 我该如何解决这个问题? 回答1 您的具体问题的解决方案是从过时的 MaybeT 包切换到 Control.Monad.Trans.Maybe 中的 Transformers 包提供的MaybeT转换器。 也就是说,请注意版本不匹配涉及base 。 如果您确实需要使用MaybeT包,则必须将
  • GHC 可以为 monad 转换器派生 Functor 和 Applicative 实例吗?(Can GHC derive Functor and Applicative instances for a monad transformer?)
    问题 我正在尝试本着mtl库的精神实现MaybeT 。 使用此非编译解决方案: {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-} import Control.Monad import Control.Monad.Trans import Control.Monad.State newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } instance (Monad m) => Monad (MaybeT m) where x >>= f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f) return a = MaybeT $ return (Just a) fail _ = MaybeT $ return Nothing instance MonadTrans MaybeT where lift m = MaybeT (liftM Just m) instance (MonadIO m) => MonadIO (MaybeT m) where liftIO m = lift (liftIO m) instance (MonadState
  • 是否有一个没有对应的monad转换器的monad(IO除外)?(Is there a monad that doesn't have a corresponding monad transformer (except IO)?)
    问题 到目前为止,我遇到的每个monad(可以表示为数据类型)都有一个对应的monad转换器,或者可能有一个。 有没有一个这样的单子吗? 还是所有单子都有对应的变压器? 对应于单子m的变压器t表示t Identity与m同构。 当然,它满足monad变换器定律,并且tn是任何monad n monad。 我想看看每个单子都有一个的证明(最好是一个有建设性的证明),或者是一个没有单子的特定单子的例子(带有证明)。 我对更多面向Haskell的答案以及(类别)理论的答案都感兴趣。 作为后续问题,是否存在一个具有两个不同的变压器t1和t2的单子m ? 也就是说, t1 Identity与t2 Identity和m同构,但是存在一个单子n ,使得t1 n与t2 n不是同构的。 ( IO和ST具有特殊的语义,因此在这里我不考虑它们,而让我们完全忽略它们。我们只关注可以使用数据类型构造的“纯”单子。) 回答1 我在此使用@Rhymoid,我相信所有Monad都有两个(!!)变压器。 我的构造有点不同,而且还不完整。 我希望能够将此草图用作证明,但我认为我或者缺少技巧/直觉和/或可能涉及其中。 由于Kleisli,每个monad( m )都可以分解为两个函子F_k和G_k ,使得F_k与G_k ,并且m与G_k * F_k同构(此处*是函子组成)。 同样,由于F_k * G_k , F_k *
  • 关于“Learn you a Haskell”的 State Monad 代码的困惑(Confusion over the State Monad code on “Learn you a Haskell”)
    问题 我正在尝试使用在线书籍 Learn you a Haskell for great Good 来了解 Haskell。 据我所知,到目前为止,我已经能够理解 Monad,直到我看到介绍 State Monad 的章节。 但是,所提供并声称是 State 类型的 Monad 实现的代码(我无法在 Hoogle 中找到它)似乎对我来说太多了。 首先,我不明白它背后的逻辑,即为什么它应该起作用以及作者如何考虑这种技术。(也许可以建议相关文章或白皮书?) 在第 4 行,建议函数 f 接受 1 个参数。 然而,在接下来的几行中,我们会看到 pop,它不需要任何参数! 扩展第 1 点,作者试图通过使用函数来表示状态来完成什么。 非常感谢任何帮助理解正在发生的事情。 编辑 敬启者, 下面的答案彻底涵盖了我的问题。 不过,我想补充一件事: 在阅读了下面建议的文章后,我找到了上面第二点的答案:一直以来,我都认为pop 函数的使用方式如下: stuff >>= pop因为在绑定类型中第二个参数是函数,而正确的用法是这个pop >>= stuff ,我在再次阅读 do-notation 如何转换为普通的 bind-lambdas 后意识到。 回答1 简短的回答: State旨在利用 monad 的特性来模拟具有局部变量的类似命令式的系统状态。 基本思想是在 monad
  • MaybeT m 的应用实例假设 Monad m(Applicative instance for MaybeT m assumes Monad m)
    问题 我一直在使用Haxl monad(在此处描述:http://www.reddit.com/r/haskell/comments/1le4y5/the_haxl_project_at_facebook_slides_from_my_talk),它有一个有趣的功能,即<*>对于它的 Applicative 实例不是与 Control.Monad 中的ap相同。 这是一个关键特性,它允许它在不阻塞的情况下进行并发计算。 例如,如果hf和ha是长计算,则 let hf :: Haxl (a -> b) = ... ha :: Haxl a = ... in do f <- hf a <- ha return (f a) 将按顺序执行它们,而 hf <*> ha 将并行执行它们,然后合并结果。 我希望能够在MaybeT Haxl运行计算,但问题是转换器包中的MaybeT m的 Applicative 实例使用了MaybeT m绑定: instance (Functor m, Monad m) => Applicative (MaybeT m) where pure = return (<*>) = ap 其中ap = liftM2 id来自Control.Monad 。 这使得 let hmf :: MaybeT Haxl (a -> b) = ... hma :: MaybeT
  • 变压器组中 ST 类型的问题(Trouble with ST's type in a transformer stack)
    问题 我在处理ST类型的forall量词时遇到了一些麻烦。 以下(简化的)代码示例工作正常,产生了预期的结果。 import Control.Monad import Control.Monad.ST return' :: a -> ST s a return' = return function :: a -> a function x = runST $ do -- Some complicated expression eventually producing a result return' x 这很好,如果我只想拥有ST 。 但是在我的计算中,我想要一个可能也会失败的状态转换器计算,所以我尝试将ExceptT添加到堆栈中。 import Control.Monad import Control.Monad.ST import Control.Monad.Except return' :: a -> ExceptT String (ST s) a return' = return function :: a -> Either String a function x = runST . runExceptT $ do -- Some complicated expression that might fail return' x 不幸的是,我收到一条相当奇怪的错误消息。
  • 在 Haskell 中为状态创建只读函数(Making Read-Only functions for a State in Haskell)
    问题 我经常遇到这样的情况,使用State monad 非常方便,因为有很多相关的函数需要以半命令的方式对同一块数据进行操作。 一些函数需要读取 State monad 中的数据,但永远不需要更改它。 在这些函数中像往常一样使用State monad 工作得很好,但我不禁觉得我已经放弃了 Haskell 的固有安全性,并复制了一种任何函数都可以改变任何东西的语言。 我可以做一些类型级别的事情来确保这些函数只能从State读取,而从不写入吗? 现在的情况: iWriteData :: Int -> State MyState () iWriteData n = do state <- get put (doSomething n state) -- Ideally this type would show that the state can't change. iReadData :: State MyState Int iReadData = do state <- get return (getPieceOf state) bigFunction :: State MyState () bigFunction = do iWriteData 5 iWriteData 10 num <- iReadData -- How do we know that the state
  • 在EitherT 中捕获异常并保留底层的monad 转换器(Catching exceptions in EitherT and preserving underlying monad transformers)
    问题 基本上我想了解如何进行异常处理。 我将exceptions包与MonadThrow / MonadCatch ,这对我来说没有多大意义。 我把它分解成我能做的最小的例子。 我很欣赏这是非常做作的。 首先,我定义了一个任意的Exception : data ReadLineException = ReadLineException deriving (Show,Typeable) instance Exception ReadLineException 然后有一个函数向用户询问一个数字,并使用 MonadWriter 跟踪发生的事情。 如果未输入数字,则使用Control.Monad.Catch throwM抛出异常。 ioTell :: (MonadWriter [String] m, MonadIO m, MonadThrow m) => m Int ioTell = do tell ["Some opening string"] liftIO $ print "Enter a number: " x <- liftIO $ getLine let mx = maybeRead x :: Maybe Int case mx of Nothing -> do tell ["Invalid entry was chosen: " ++ show x] throwM
  • 在恒定空间(堆和堆栈)中使用 State monad 进行 Monadic 折叠?(Monadic fold with State monad in constant space (heap and stack)?)
    问题 是否可以在常量堆栈和堆空间中的 State monad 中执行折叠? 还是不同的功能技术更适合我的问题? 接下来的部分描述了问题和一个激励用例。 我正在使用 Scala,但也欢迎 Haskell 中的解决方案。 折叠State Monad 填充堆 假设 Scalaz 7. 考虑 State monad 中的 monadic fold。 为了避免堆栈溢出,我们将蹦床折叠。 import scalaz._ import Scalaz._ import scalaz.std.iterable._ import Free.Trampoline type TrampolinedState[S, B] = StateT[Trampoline, S, B] // monad type constructor type S = Int // state is an integer type M[B] = TrampolinedState[S, B] // our trampolined state monad type R = Int // or some other monoid val col: Iterable[R] = largeIterableofRs() // defined elsewhere val (count, sum): (S, R) = col.foldLeftM[M
  • Monad transformers: Implementation of a stack machine with MaybeT (State Stack)
    I'm trying to implement a Maybe-State monad transformer and use it to implement a simple stack machine. The definitions of state monad and maybe should be correct. Now I'm trying to implement pop: pop :: MaybeT (State Stack) Int So that if the stack is empty it returns nothing, otherwise it returns Just <popped stack>. This is what I have so far: pop :: MaybeT (State Stack) Int pop = guard True (do (r:rs) <- get put rs return r) (Obviously True is just a dummy placeholder - I'll implement the condition later, for now I want to get the other part right). What is wrong with my code? From my
  • Can GHC derive Functor and Applicative instances for a monad transformer?
    I'm trying to implement MaybeT in the spirit of the mtl library. With this non-compiling solution: {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-} import Control.Monad import Control.Monad.Trans import Control.Monad.State newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } instance (Monad m) => Monad (MaybeT m) where x >>= f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f) return a = MaybeT $ return (Just a) fail _ = MaybeT $ return Nothing instance MonadTrans MaybeT where lift m = MaybeT (liftM Just m) instance (MonadIO m) => MonadIO
  • Monad用简单的英语? (对于没有FP背景的OOP程序员)(Monad in plain English? (For the OOP programmer with no FP background))
    问题 用OOP程序员会理解的术语(没有任何函数式编程背景),什么是monad? 它解决了什么问题,最常使用的地方是什么? 更新 为了阐明我正在寻找的理解类型,假设您正在将具有monad的FP应用程序转换为OOP应用程序。 您将如何将monad的责任移植到OOP应用程序? 回答1 更新:这个问题是一个非常长的博客系列的主题,您可以在Monads上阅读该博客系列-感谢您提出的很棒的问题! 用OOP程序员会理解的术语(没有任何函数式编程背景),什么是monad? monad是一种类型的“放大器”,它遵循某些规则并提供某些操作。 首先,什么是“类型放大器”? 我的意思是说,某个系统可以让您将一种类型转换为更特殊的类型。 例如,在C#中考虑Nullable<T> 。 这是一种放大器。 它允许您采用一个类型,例如int ,并为该类型添加新功能,即现在可以在以前无法使用的情况下将其设置为null。 作为第二个示例,请考虑IEnumerable<T> 。 它是一种类型的放大器。 它允许您采用一种类型,例如string ,并为该类型添加新功能,即,您现在可以从任意数量的单个字符串中组成一系列字符串。 什么是“某些规则”? 简而言之,存在一种合理的方式,使基础类型上的功能在放大类型上起作用,以使它们遵循功能组成的正常规则。 例如,如果您有一个整数函数,请说 int M(int x) { return
  • 如何在不溢出堆栈的情况下将 IO 与 Scalaz7 Iteratees 一起使用?(How to use IO with Scalaz7 Iteratees without overflowing the stack?)
    问题 考虑此代码(取自此处并修改为使用字节而不是字符行)。 import java.io.{ File, InputStream, BufferedInputStream, FileInputStream } import scalaz._, Scalaz._, effect._, iteratee.{ Iteratee => I, _ } import std.list._ object IterateeIOExample { type ErrorOr[+A] = EitherT[IO, Throwable, A] def openStream(f: File) = IO(new BufferedInputStream(new FileInputStream(f))) def readByte(s: InputStream) = IO(Some(s.read()).filter(_ != -1)) def closeStream(s: InputStream) = IO(s.close()) def tryIO[A, B](action: IO[B]) = I.iterateeT[A, ErrorOr, B] { EitherT(action.catchLeft).map(r => I.sdone(r, I.emptyInput)) } def enumBuffered(r: =
  • Applicative instance for MaybeT m assumes Monad m
    I've been using the Haxl monad (described here: http://www.reddit.com/r/haskell/comments/1le4y5/the_haxl_project_at_facebook_slides_from_my_talk), which has the interesting feature that <*> for its Applicative instance isn't the same as ap from Control.Monad. This is a key feature that allows it to do concurrent computations without blocking. For example, if hf and ha are long computations, then let hf :: Haxl (a -> b) = ... ha :: Haxl a = ... in do f <- hf a <- ha return (f a) will do them sequentially, while hf <*> ha will do them in parallel and then combine the results. I would like to be