采用整数的monad的简单示例

0 monads haskell functional-programming

我根据对Monads(https://www.youtube.com/watch?v=ZhuHCtR3xq8)的解释,编写了一个组成函数f和g的Monad .解释停在一个关键组成部分:组成一个函数(比如F)a -> ma与另一个(说G) a -> ma,您需要一种方法来转换maa,拿东西出来的单子容器的(否则怎么会进给量f的输出成g ??)并没有解决.

假设我们有f和g映射整数并返回一个Maybe:

f :: Int -> Maybe Int
f = \x -> (Just x)

g :: Int -> Maybe Int
g = \x -> (Just x)
Run Code Online (Sandbox Code Playgroud)

我想制作一个允许我编写f和g的Monad,以便可以评估(g o f)(x)(含义f(g(x))).为了使这个工作,我们需要一种方法来转换Maybe Int(f的输出),Int以便它可以发送到g.当Maybe容器中有值时,我们只需拉出值.当g的输出为Nothing时,我们可以考虑值0(我知道g的输出不能超过上面的g,但我们假设它可以用于另一个f).

这是我尝试定义执行此操作的Monad MyMonad失败的尝试:

f :: Int -> Maybe Int
f = \x -> (Just x)

g :: Int -> Maybe Int
g = \x -> (Just x)

data MyMonad a = Maybe a

instance Monad MyMonad where
  return x = MyMonad x
  Just x >>= (\x -> MyMonad (Just x))
  Nothing >>= (\x -> MyMonad (Just 0))
Run Code Online (Sandbox Code Playgroud)

谁能澄清这里有什么问题?从教程中很难知道在函数内部进行模式匹配的正确方法是什么(在这里处理Just vs. Nothing的情况)以及梳理实例化Monad的所有不同语法.这个例子没有帮助(https://wiki.haskell.org/All_About_Monads#Maybe_a_monad):引入绑定后>>=的羊例子甚至不使用它,采用了组合子来代替.

4ca*_*tle 5

当你第一次开始学习monad时,最容易学习的就是Identitymonad.看起来这就是你实际上想要实现的东西,但是你已经把这个词Maybe卡在那里的某个地方,并且它正在抛弃一切.(那,或者你实际上是在尝试实现Maybemonad,但你没有定义JustNothing在任何地方.)

如果MyMonadIdentitymonad那样,正确的定义是:

f :: Int -> MyMonad Int
f = \x -> MyIdentity x

g :: Int -> MyMonad Int
g = \x -> MyIdentity x

data MyMonad a = MyIdentity a

instance Monad MyMonad where
    return x = MyIdentity x     -- return = \x -> MyIdentity x
    (MyIdentity x) >>= f = f x  -- (>>=) = \(MyIdentity x) f -> f x
Run Code Online (Sandbox Code Playgroud)

如果MyMonadMaybemonad那样,正确的定义是:

f :: Int -> MyMonad Int
f = \x -> MyJust x

g :: Int -> MyMonad Int
g = \x -> MyJust x

data MyMonad a = MyNothing | MyJust a

instance Monad MyMonad where
    return x = MyJust x
    (MyJust x) >>= f = f x
    MyNothing  >>= f = MyNothing
Run Code Online (Sandbox Code Playgroud)

(注意,要编译这些,您还需要为Functor和定义一个实例Applicative.)

PS定义>>=Maybe使用lambda符号单子,你需要一个case表达式:

(>>=) = \m f -> case m of
    MyJust x  -> f x
    MyNothing -> MyNothing
Run Code Online (Sandbox Code Playgroud)

  • @ user8379674例如,状态monad可以被认为是"包含"单个"a",但只能在对不相关类型`s`执行某些计算之后.所以要求一个'state sa - > a`类型的函数是不明智的,因为在生成一个`a`之前我们必须有一个`s`来计算.然而,在我到目前为止提到的所有情况中,有可能将`a - > mb`转换为`ma - > mb`而不先将其变成'a - > b`; 从某种意义上说,这样做的可能性是monad抽象的全部要点. (5认同)
  • 特别要注意的是,在其中任何一个中都没有定义`MyMonad a - > a`类型的函数.@ user8379674多次声明这是必需的,但它根本不是 - 实际上对于`MyMonad`的第二个定义,它不可能*用这种类型定义一个合理的函数! (4认同)
  • @ user8379674 ...并且,作为一个更高级别的评论:虽然我可以继续,但我认为在这一点上抽象地谈论monads是有点乐观的.通过实现和使用几个不同的monad(通过具体和讨论具体的monad),你将通过思考和讨论monad的完全通用性来获得更好的直觉. (3认同)
  • @ user8379674我不确定我能解释*为什么*它不需要,但我可以提供一些证据证明这是一个思考问题的坏方法.首先:如果在上面的代码中没有类型`MyMonad a - > a`的函数,并且你同意上面的代码完全实现了`MyMonad`的monad,那么这应该是100%令人信服的证据, a在实现monad的过程中,没有必要定义类型为"MyMonad a - > a"的函数.采取另一种策略:你似乎认为`ma`是"包含"一个'a`.(续) (2认同)