关于Haskell中monad的一些问题

Sta*_*ked 11 monads haskell

我正在学习monads并且有一些问题.

这就是我现在所处的位置.请纠正我错在哪里.

  • >>=标志为中缀运算符.中缀运算符是带有两个参数(左侧和右侧)并返回值的函数.

  • >>=符号称为绑定运算符并具有签名Monad m => m t -> (t -> m u) -> m u.但是,这些类型似乎没有排在这里.我们得到一个类型的值,m t第二个参数是一个带有a的函数t.(我不知道如何连接点.)

  • 这必定意味着绑定功能,在某种程度上能够去除mm t为了得到t并把它传递给函数.

这是我的问题:

  • 是否能够mm t仅在此类绑定运算符内部执行的操作中删除.这个绑定运算符是否有一些特殊的特权?

  • 它与状态变化有什么关系?我理解(我认为)monad的目标是"包装"副作用,以便它们与程序的其余部分隔离开来.但是绑定运算符在这方面的作用是什么?

Don*_*art 12

是能够从'M t'移除'M'的东西,只有在这样的绑定操作符中才可能.

嗯,它肯定可以在bind运算符中,因为它的类型指定:

(>>=) :: m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)

你的monad的'run'函数通常也可以这样做(从你的计算中返回一个纯值).

monads的目标是"包装"副作用,使它们与程序的其余部分隔离开来

嗯.不,monads让我们模拟计算的概念.副作用计算只是一个这样的概念,如状态,回溯,延续,并发,事务,可选结果,随机结果,可恢复状态,非确定性......所有这些都可以描述为monad

我假设IO monad是你所指的.这是一个有点奇怪的单子 - 它会生成对世界状态的抽象变化序列,然后由运行时进行评估.绑定只是让我们按照IO monad中的正确顺序对事物进行排序 - 然后编译器将所有这些按顺序排列的世界修改操作转换为更改该机器状态的命令性代码.

这对IO monad来说非常具体,而不是monad.

  • 假设monadic类型没有隐藏,任何函数都可以拆分M,但是,do-notation会隐藏大部分管道,意味着只有`>> =`来解构内部状态.只有bind和runM函数解构状态只是一个成语,它不是必需的. (2认同)

sth*_*sth 10

能否从'M t'移除'M'只能在这样的绑定操作符中执行.这个绑定运算符是否有一些特殊的特权?

绑定绝不是一种特殊情况,但通常它将与monads数据类型在同一模块中定义.因此,它可能知道(和使用)模块未导出的详细信息.通常的情况是模块导出数据类型,但不是它的构造函数或关于类型内部结构的其他细节.然后,对于使用该模块的代码,数据类型的内部工作是不可见的,并且该代码不能直接修改此类型的值.

与模块内部定义的函数相反,例如某些绑定操作符>>=,可以从它们所定义的模块中访问它们所喜欢的任何内容.因此,这些函数可能能够执行"外部"函数无法做到的事情.

一个特例是IOmonad,因为它不是由模块定义的,而是内置于运行时系统/编译器中.在这里,编译器知道它的实现的内部细节,并公开像IOs 这样的函数>>=.这些函数的实现确实是特权的,因为它们生活在"程序之外",但这是一个特例,并且这个事实不应该在Haskell中观察到.

它与状态变化有什么关系?我理解(我认为)monad的目标是"包装"副作用,以便它们与程序的其余部分隔离开来.但是绑定运算符在这方面的作用是什么?

它实际上并不需要与状态更改有关,这只是一个可以用moand处理的问题.该IO单子用于已IO以特定顺序执行,但通常单子只是组合功能一起的方法.

通常,monad(特别是它的绑定函数)定义了一种方法,其中某些函数应该组合成更大的函数.这种组合函数的方法在monad中被抽象出来.这种组合的工作原理或者为什么要以这种方式组合函数并不重要,monad只是指定了以某种方式组合某些函数的方法.(另请参阅"Monads for C#程序员"的回答,我基本上重复了几次示例.)


yfe*_*lum 5

以下是类型类的定义Monad.

class  Monad m  where

    (>>=)       :: forall a b. m a -> (a -> m b) -> m b
    (>>)        :: forall a b. m a -> m b -> m b
    return      :: a -> m a
    fail        :: String -> m a

    m >> k      = m >>= \_ -> k
    fail s      = error s
Run Code Online (Sandbox Code Playgroud)

type-class的每个type-in​​stance都Monad定义了自己的>>=函数.以下是类型实例的示例Maybe:

instance  Monad Maybe  where

    (Just x) >>= k      = k x
    Nothing  >>= _      = Nothing

    (Just _) >>  k      = k
    Nothing  >>  _      = Nothing

    return              = Just
    fail _              = Nothing
Run Code Online (Sandbox Code Playgroud)

正如我们所看到的,因为Maybe版本>>=是专门定义理解Maybe类型实例,因为它是在具有法定访问的地方定义的data Maybe a数据构造函数NothingJust a,该Maybe版本>>=能够解开了a在的Maybe a和通他们通过.

通过一个例子,我们可以采取:

x :: Maybe Integer
x = do a <- Just 5
       b <- Just (a + 1)
       return b
Run Code Online (Sandbox Code Playgroud)

脱糖,符号变为:

x :: Maybe Integer
x = Just 5        >>= \a ->
    Just (a + 1)  >>= \b ->
    Just b
Run Code Online (Sandbox Code Playgroud)

评估为:

  =                  (\a ->
    Just (a + 1)  >>= \b ->
    Just b) 5

  = Just (5 + 1)  >>= \b ->
    Just b

  =                  (\b ->
    Just b) (5 + 1)

  = Just (5 + 1)

  = Just 6
Run Code Online (Sandbox Code Playgroud)