Monad 类型签名示例

Monad type signature example

(+) 的类型签名是:

    (+) :: Num a => a -> a -> a

我可以在以下位置看到这个:

    + 4 5

结果为 9。+ 取 4 和 returns 函数大致为:

    (4 + a) -> a

...然后取 5 并计算为 9。基本上,两件事进来,一件事情出去。我看不出这是如何使用绑定运算符的类型签名工作的。对我来说,在实践中,它看起来总是一进一出。

有人可以像我上面为 (+) 所做的那样使用 Maybe monad 来指导我完成一个简单的示例吗?希望这对像我这样的 Haskell 新手大体上有用!

这里是绑定的类型签名:

(>>=)
    :: Monad m
    => m a         -- Left argument
    -> (a -> m b)  -- Right argument
    -> m b

这是一个带有两个参数的绑定示例:

Just 1 >>= (\n -> Just (n + 1))
^^^^^^     ^^^^^^^^^^^^^^^^^^^^
Arg #1     Arg #2

.. 计算结果为 Just 2

Could someone please walk me through a simple example using the Maybe monad the way I've done above for (+)?

(>>=) 结合了一个单子动作和一个函数,returns 一个单子动作:

(       >>=            ) :: Maybe Int -> (Int -> Maybe Bool) -> Maybe Bool
(Just 1 >>=            ) ::              (Int -> Maybe Bool) -> Maybe Bool
(Just 1 >>= Just . even) ::                                     Maybe Bool

(+) 完全一样,两件事进入(一个单子动作和一个返回单子动作的函数),一个东西出来(一个单子动作)。

To me, in practice, it always looks like one in, one out.

请注意 Haskell 单子与 APL 单子无关,后者确实是一元函数。

人们在看到 >>= 类型签名时很困惑的一点是,它看起来不平衡

如果你选择 + 你会得到这样的签名:

(+) :: Num a 
    => a  -- 1st arg
    -> a  -- 2nd arg
    -> a  -- return-type

如果你选择 . 你会得到这个:

(.) :: (b -> c) -- 1st arg, a function from b to c
    -> (a -> b) -- 2nd arg, a function from a to b
    ->  a -> c  -- return-type, a function from a to c

到目前为止没有什么可怕的

现在看看>>=

(>>=) :: Monad m
      =>       m a  -- 1st arg, a monad a
      -> (a -> m b) -- 2nd arg, a function from a to a monad b
      ->       m b  -- return-type, a monad b

第一个参数与第二个参数不匹配,但没关系,我会说明原因。

假设您有以下两个功能:

f :: Monad m => a -> m a -- we just need the type signatures
g :: Monad m => a -> m a

然后我们执行以下操作:

\a -> f a >>= \b -> g b

f a 的类型是什么?是 m ag b 的类型是什么?这是 m b

基本上我所做的是这样的:

function: \a -> f a >>= \b -> g b
types   :  a -> m a      b -> m b

>>= 的参数类型是什么?再看:

function: \a -> f a >>= \b -> g b
types   :  a -> m a      b -> m b
>>=-args:       m a  -> (b -> m b)

所以本质上我们在这里所做的是通过向表达式添加一个 lambda,我们已经完成了 制作签名的 "missing" 类型信息"lop-sided"

\n -> (Just n >>= (\m -> Just (m + 1))) -- added extra () for highlighting

或换句话说:

fn a = Just a >>= (\m -> Just (m + 1))
fn 3 -- returns Just 4

基本上我刚才所做的是创建一个函数 fn,签名为 a -> m a... 与 fg 完全相同。所以 >>= 是一种组合单子函数的方法。就像 . 是一种组合 普通 函数的方法。

观看 [[=​​34=]] 这个答案的灵感来源,最终让我有点理解为什么它看起来像它的样子。