【问题标题】:How to apply a custom Monad Transformer如何应用自定义 Monad Transformer
【发布时间】:2016-09-09 12:03:12
【问题描述】:

假设我有一些 Monadic 类型

data Example a = CheckIt {unwrap :: a}

instance Functor Example where
  fmap f (CheckIt x) = CheckIt (f x)

instance Applicative Example where
  pure = CheckIt
  CheckIt f <*> CheckIt x = CheckIt (f x)

instance Monad (Example) where
  return = CheckIt
  e@(CheckIt a) >>= f = f a

我有一个函数可以根据一些输入返回[a]

fetchList :: b -> [Int]
fetchList _ = [1,2,3,4]

还有一个返回 IO [a] 的函数(从实际实现中简化):

basicIoWrap :: [a] -> IO [a]
basicIoWrap x = return x

我希望运行这个 IO,然后从中提取一个示例 [a]:

以下不起作用:

 foo :: b -> Example [a]
 foo val = (basicIoWrap (fetchList val)) >>= \list -> return list

抱怨不同的单子类型

 Couldn't match type ‘IO’ with ‘Example’
      Expected type: Example [a]
        Actual type: IO [Int]

所以我知道这正是 Monad 转换器的用例,但我真的很难弄清楚如何在上下文中应用它们。假设我有一个变压器:

newtype ExampleT m a = ExampleT {runExampleT :: m (Example a)}

我将我的签名改写为 foo :: b -> ExampleT (IO [a])

我不清楚函数体会是什么样子,以及我最终如何从中提取示例 [a]? runExampleT ExampleT (IO [a]) 不会给出IO [Example a],从而简单地将多单子问题推到更远的地方吗?

【问题讨论】:

  • 缺少各种不安全的“转义”函数,您无法从 IO monad 中删除列表以返回 Example [a]。没有IoT 转换器的原因是因为IO monad,如果使用,必须在堆栈的底部,这意味着任何堆栈的最外面的monad 是IO
  • 那么这种情况一般是怎么处理的呢?
  • monad 转换器主要是向现有 monad 添加行为,而不是从中提取值。如果foo 返回一个IO (Example [a])(正如@user2297560 击败我的建议),那么编写一个bar :: Example [a] -&gt; IO [a] 类型的函数来检索内部列表(同时将其保存在IO 上下文中)相对容易。有了这样一个函数,你就可以写foo &gt;&gt;= bar

标签: haskell monads monad-transformers


【解决方案1】:

你永远不能安全地从IO“逃脱”,但是如果你有一个像Example (IO [a])Example这样的类型的值至少是Traversable,那么你可以把它变成IO (Example [a]) sequence 函数。使用这种方法,您可以将 foo 函数编写为:

foo :: b -> IO (Example [a])
foo = sequence . return . basicIoWrap . fetchList

由于您必须已经在IO monad 中工作才能使用basicIoWrap,因此您可以访问Example [a]。例如:

do input <- getLine
   (Example as) <- foo input
   mapM_ print as

【讨论】:

  • 请注意,Example 需要一个 Traversable 实例,以便 sequenceExample (IO [a]) 值转换为 IO (Example [a]) 值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-09
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 2011-07-01
  • 1970-01-01
  • 2014-05-03
相关资源
最近更新 更多