标签: monad-transformers

结合StateT和State monads

让我们说我有一个功能

f :: State [Int] Int
Run Code Online (Sandbox Code Playgroud)

和功能:

g :: StateT [Int] IO Int
Run Code Online (Sandbox Code Playgroud)

我想用fg,并通过他们之间的状态.是否有库函数
StateT (return . runState f)?或者一般来说,给定一个具有相应monad的monad变换器,它有一个库函数吗?

monads haskell state-monad monad-transformers

16
推荐指数
2
解决办法
1726
查看次数

结合F#异步和计算表达式

假设我想Optionasync工作流程中返回一段时间:

let run = 
    async {
        let! x = doAsyncThing
        let! y = doNextAsyncThing x
        match y with
        | None -> return None
        | Some z -> return Some <| f z
    }
Run Code Online (Sandbox Code Playgroud)

理想情况下,我会使用FSharpx中的可能计算表达式同时作为异步来避免这样做match.我可以创建一个自定义构建器,但是有没有办法一般地组合两个计算表达式?它可能看起来像这样:

let run = 
    async {
        let! x = doAsyncThing
        let! y = doNextAsyncThing x
        return! f y
    }
Run Code Online (Sandbox Code Playgroud)

monads f# asynchronous monad-transformers computation-expression

16
推荐指数
2
解决办法
2304
查看次数

没有monad变换器的monad的明确示例是什么?

Monad变换器以所有标准monad(Reader,Writer,State,Cont,List等)而闻名,但这些monad变换器中的每一个都以稍微不同的方式工作.在给定具有monad实例的类型构造函数的定义的情况下,没有用于构造monad变换器的通用方法或公式.因此,不能保证根据某些任意业务要求设计的monad数据类型将具有monad变换器.有没有这样一个明确的例子?

相关工作

另一个问题解释了两个monad的仿函数组合不一定是monad.另见这个问题.这些例子没有回答当前的问题 - 它们仅仅说明了没有构造单子变压器的一般方法的问题.这些例子表明,给定两个单子M和N,我们有时会发现M(N a)是单子,有时N(M a)是单子,有时也不是单子.但这既没有说明如何为M或N构造monad变换器,也没有表明它是否存在.

另一个问题的答案认为,IO单子不能有一个单子转换,因为如果它有一个IOT,我们可以申请IOTList,然后抬起空列表(lift [])到生成的单子就必须撤消副作用的进行"早期" IO monad.这个论点是基于IOmonad"实际上执行"可能无法撤消的副作用的想法.但是,IOmonad不是显式类型构造函数.

讨论

在明确给出monad类型的每个例子中,可以以某种方式找到monad变换器, - 有时需要一定的独创性.例如,最近发现ListT存在于Haskell库中的变换器以微妙的方式发生错误,但最终通过更改定义来解决问题.ListT

没有变换器的monad的标准示例是monad,例如IO,实际上不是由显式类型构造函数定义的 - IO是库以某种方式在低级别定义的不透明"魔术"类型.很明显,无法IO纯函数赋予monad实例定义为显式类型构造函数.该IO示例显示,如果我们允许monad实例包含具有不纯副作用的隐藏低级代码,则monad转换器可能无法存在.所以,让我们将注意力限制在使用纯函数实现的monad上.

似乎没有一种算法可以从monad的源代码中自动导出monad变换器.我们甚至知道这总是可能的吗?

为了让我更清楚一个monad的"明确例子"我的意思:假设我声称

 type Q u v a = ((u -> (a, Maybe a)) -> v) -> u -> (a, Maybe a)
Run Code Online (Sandbox Code Playgroud)

可以有一个合法的Monad实例相对于所述类型参数 …

monads haskell functional-programming monad-transformers

16
推荐指数
1
解决办法
390
查看次数

试图理解monad变换器产生的类型

提供这个组合两个monad的例子的文档Control.Monad.Trans.Error:

type ErrorWithIO e a = ErrorT e IO a
==> ErrorT (IO (Either e a))
Run Code Online (Sandbox Code Playgroud)

我觉得这是违反直觉的:即使ErrorT是所谓包装 IO,它看起来像该错误的信息已经注入了IO操作的结果类型.我会期待它

==> ErrorT (Either e (IO a))
Run Code Online (Sandbox Code Playgroud)

基于"包装"一词的通常含义.

为了让事情更加混乱,StateT每个人都有一些:

type MyError e = ErrorT e Identity  -- (see footnote)
type StateWithError s e a = StateT s (MyError e) a
==> StateT (s -> ErrorT (Either e (a, s)))
Run Code Online (Sandbox Code Playgroud)

状态类型s已被注入EitherRight侧,但整个Either也被包裹在一个功能.

为了使事情变得更加混乱,如果单子相结合的其他方式:

type …
Run Code Online (Sandbox Code Playgroud)

monads haskell monad-transformers

15
推荐指数
2
解决办法
686
查看次数

致力于置换monad变压器堆栈

我发现monad变换器的一个问题是需要lift将操作转换为正确的monad.单lift在这里和那里也不错,但有时也有功能类似如下:

fun = do
  lift a
  lift b
  c
  lift d
  lift e
  f
Run Code Online (Sandbox Code Playgroud)

我希望能够这样编写这个函数:

fun = monadInvert $ do
  a
  b
  lift c
  d
  e
  lift f
Run Code Online (Sandbox Code Playgroud)

这会减少lifts 的数量并使代码更清晰.

问题是:对于monads是monadInvert可能的?应该如何创建这个功能?

加分点:定义它monad m的实例MonadIO.

这个问题的标题提到了排列:实际上,我们如何处理monad变换器堆栈的任意排列?

monads haskell monad-transformers

15
推荐指数
2
解决办法
459
查看次数

用于NonEmptyList的Monad变换器?

在我看来,Scalaz' NonEmptyList有一个monad实例,所以应该有一个monad变换器(有点类似ListT).那是对的吗?

如果是的话,那里有一个吗?(我在Scalaz 7中找不到一个.)

如果没有,即monad变压器是不可能的或没有任何意义,我将不胜感激任何其他解释为什么不.

monads scala monad-transformers scalaz

15
推荐指数
1
解决办法
484
查看次数

如何使用可扩展效果获得“单子转换器的不灵活语义”?

考虑以下示例。

newtype TooBig = TooBig Int deriving Show

choose :: MonadPlus m => [a] -> m a
choose = msum . map return

ex1 :: (MonadPlus m, MonadError TooBig m) => m Int
ex1 = do
    x <- choose [5,7,1]
    if x > 5
        then throwError (TooBig x)
        else return x

ex2 :: (MonadPlus m, MonadError TooBig m) => m Int
ex2 = ex1 `catchError` handler
  where
    handler (TooBig x) = if x > 7
        then throwError (TooBig x)
        else …
Run Code Online (Sandbox Code Playgroud)

monads haskell functional-programming monad-transformers free-monad

15
推荐指数
1
解决办法
167
查看次数

为什么monad变换器不能限制产生monad?

MonadTrans类中:

class MonadTrans t where
    -- | Lift a computation from the argument monad to the constructed monad.
    lift :: Monad m => m a -> t m a
Run Code Online (Sandbox Code Playgroud)

为什么不被t m限制为Monad?即,为什么不:

{-# LANGUAGE MultiParamTypeClasses #-}
class Monad (t m) => MonadTrans t m where
  lift :: Monad m => m a -> t m a
Run Code Online (Sandbox Code Playgroud)

如果答案是"因为那就是它的方式",那很好 - 这只会让n008感到困惑.

monads haskell typeclass monad-transformers

14
推荐指数
1
解决办法
338
查看次数

有懒惰/严格版本的Writer有什么意义?

为什么Haskell中有两个不同的Writer类型monad?直觉上,读"严格的作家monad"意味着<>严格,所以日志中没有thunk积累.但是,查看源代码,事实证明并非如此:

-- Lazy Writer
instance (Monoid w, Monad m) => Monad (WriterT w m) where
-- ...
m >>= k  = WriterT $ do
    ~(a, w)  <- runWriterT m
    ~(b, w') <- runWriterT (k a)
    return (b, w <> w')
Run Code Online (Sandbox Code Playgroud)

在严格的版本中,模式不是无可辩驳的,即~缺失.所以上面发生的是,m并且k a没有评估,但存储为thunk.在严格版本中,它们被评估以检查它们是否与元组模式匹配,结果被馈送到<>.在这两种情况下,在>>=实际需要产生的值之前不会对其进行评估.所以我理解它的方式是懒惰和严格版本都做同样的事情,除了它们在定义中的不同位置有thunk >>=:lazy产生runWriterTthunks,strict产生<>thunk.

这让我有两个问题:

  1. 是上面的权利,还是我在这里误解了评价?
  2. 我可以在<>不编写自己的包装器和实例的情况下完成严格吗?

monads haskell writer monad-transformers

14
推荐指数
1
解决办法
807
查看次数

在像MonceptT IO这样的monad堆栈中管理资源的最佳方法是什么?

无论好坏,Haskell流行的Servant库使得在monad变换器堆栈中运行代码变得很普遍ExceptT err IO.仆人自己的处理程序monad是ExceptT ServantErr IO.正如许多人所说,这是一个有点麻烦的monad工作,因为有多种方法可以展开失败:1)通过IO基地的正常例外,或2)返回Left.

正如Ed Kmett的exceptions图书馆有助于澄清:

基于连续的monad和诸如ErrorT e IO提供多种故障模式的堆栈是this [ MonadMask]类的无效实例.

这非常不方便,因为MonadMask我们可以访问有用的[多态版本] bracket函数来进行资源管理(不会因异常而泄漏资源等).但是在Servant的Handlermonad我们不能使用它.

我对它不是很熟悉,但是有些人说解决方案是使用monad-control它和许多合作伙伴库一样,lifted-base并且lifted-async让你的monad访问资源管理工具bracket(大概这适用于ExceptT err IO和朋友一样?).

然而,似乎monad-control失去了在社会上赞成,但我不能告诉替代将是什么.即使Snoyman最近的safe-exceptions图书馆使用Kmett的exceptions库也避免了monad-control.

有人可以为像我这样试图为严重的Haskell使用方式的人们澄清当前的故事吗?

resources haskell exception-handling monad-transformers io-monad

14
推荐指数
1
解决办法
580
查看次数