Haskell中的“=>”符号是什么意思?

15

出于某种原因,我找不到这个答案。我尝试在Google中搜索“Haskell等号箭头”,但没有得到任何结果。假设我们有以下函数:

sendMessage :: MonadM e m => Message -> m ()
sendMessage message = do
    mClient  <- getMessageClient
    liftIO $ send mClient message

e和m究竟在哪里使用?它们被传递到消息对象(函数?)中,然后作为单个类型m()输出吗?

我认为我对Haskell非常陌生,所以任何帮助都将不胜感激。


1
这是类型上下文:https://www.haskell.org/tutorial/classes.html - Lee Duhem
@LeeDuhem,您能简单地解释一下这句话的意思吗?作为一个不会编写Haskell程序的人,我很难理解您发送的链接。 - Niko
这一定是一个重复的副本,但我不知道如何找到旧的副本。 - dfeuer
4
如果你来自Java,那么类型类有点像接口。 - Dan
看起来你的问题已经得到了回答 :-) - Lee Duhem
2个回答

15

首先,如果你想知道某个操作符具体是做什么的,请不要问StackOverflow,而是向 Hoogle 提问!

但实际上,Hayoo 对于特定的 => 并没有用处,因为与 Haskell 中几乎所有其他内容不同,这是内置语法而不是在某个库中定义的操作符。

您的签名

sendMessage :: MonadM e m => Message -> m ()

意思是: sendMessage 的类型为 Message -> m(),其中m可以是任何具有MonadM类型类实例的monad。

这可能对您没有太大帮助,因为实际上MonadM是一个相当复杂的类型类。更好地考虑一个更简单的例子:

sum :: Num n => [n] -> n
这意味着:sum的类型是[n] -> n,其中n可以是任何数字类型,该类型是Num类的实例,即支持减法、乘法、显然还有加法的类型类。实际上这种语法是一种简写形式。
sum :: ∀ n . Num n => [n] -> n

这意味着对于所有满足约束Num n的类型n,函数sum具有签名[n] -> n

您可以使用任何具体数字类型来实例化这样的多态函数,例如:

sum :: [Int] -> Int

在您的示例中,您可能会将其实例化为类似以下内容:

sendMessage :: Message -> MessageT IO ()

感谢提供Hayoo的参考资料;我会经常使用它。所以,如果我理解正确,=>符号前面的任何内容都只是匹配输入/输出元素的类型限制吗? - Niko
1
基本上是的。事实上,最好先忽略约束条件,考虑一个示例实例化或无约束多态函数,以弄清楚正在发生的事情。 - leftaroundabout
明白了。感谢您的帮助。 - Niko
使用hoogle代替hayoo,因为后者自2012年以来没有更新,上面的链接也无法访问。 - Roland Puntaier
@RolandPuntaier 是的,谢谢。请不要犹豫,在未来直接将这样的评论作为“编辑”提出。 - leftaroundabout

3

类型签名

sendMessage :: MonadM e m => Message -> m ()

可以被读取

假设约束条件 MonadM e m 成立,sendMessage 的类型为 Message -> m ()

MonadM(几乎肯定)是一个多参数类型类,具有功能依赖。它的定义可能看起来模糊不清,比如:

class Monad m => MonadM e m | m -> e where ....

现在您不需要担心这个问题。编写这样的类是一个相对高级的主题。但它表达了一些操作可以使类型em相关联,其中类型e由类型m确定。


那么e和m仍然是这个函数的输入吗?还是只有消息?或者...两者都有? - Niko
这个函数的输入只是一个 Message。输出可以是您选择的任何 m 类型,只要 m 是类型类 MonadM e m 的实例。 - amalloy
@Niko:它们是函数的“类型级别参数”,如果你愿意这样说的话。但从这个角度来看并不一定有帮助。 - leftaroundabout
好的,我想我明白了。我唯一的问题是如果你不知道e是什么,你怎么能验证m的类型是否为MonadM e m?或者我对“e”是什么有误解吗? - Niko
@Niko,你不需要担心这里的 e,因为它似乎与 sendMessage 无关,尽管它可能对其他操作很重要。无论实例 m 有什么问题,e 都将被修复。你需要检查文档或 GHC,看看你特定的 m 是否有一个实例。还要注意,m 一种类型,并没有 类型 MonadM e m,而是满足约束条件 MonadM e m - dfeuer
@dfeuer,这下明白了。感谢您的耐心。 - Niko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接