绑定/赋值运算符适用于返回String的函数,但不适用于返回Int的函数

art*_*lla 1 haskell ghc ghci

为什么Prog A编译运行正常,而Prog B无法编译?谢谢

Prog A.

func :: String -> String
func a = a

mydofn a = do 
  x <- func a
  return x

main = print "Finished"
Run Code Online (Sandbox Code Playgroud)

Prog B.

func :: Int -> Int
func a = a

mydofn a = do 
  x <- func a
  return x

main = print "Finished"
Run Code Online (Sandbox Code Playgroud)

Prog B编译错误:

Couldn't match expected type `m0 t0' with actual type `Int'
In the return type of a call of `func'
In a stmt of a 'do' block: x <- func a
In the expression:
  do { x <- func a;
       return x }
Run Code Online (Sandbox Code Playgroud)

Mik*_*kov 6

使用do-notation,此代码:

mydofn a = do 
  x <- func a
  return x
Run Code Online (Sandbox Code Playgroud)

只是语法糖

mydofn a = func a >>= (\x -> return x)
Run Code Online (Sandbox Code Playgroud)

现在,>>=有型Monad m => m a -> (a -> m b) -> m b,但在第二个例子中,应用程序func a有一个类型Int,不能用统一Monad m => m a(因为Int是自己的,而不是内部的一些m),这是什么类型检查告诉你("无法匹配m aInt").但为什么这在第一种情况下起作用?

Haskell中的字符串只是字符列表([Char]).在标准库中一个Monad实例,[a]如下所示:

instance  Monad []  where
    m >>= k             = foldr ((++) . k) [] m
    return x            = [x]
Run Code Online (Sandbox Code Playgroud)

所以[Char]Monad m => m a(m = []a = Char)统一,你的第一个例子就变成了

mydofn a = foldr ((++) . (\x -> [x])) [] (func a)
Run Code Online (Sandbox Code Playgroud)

或者等价的

mydofn a = concat . map (\x -> [x]) $ func a
Run Code Online (Sandbox Code Playgroud)

这只是将字符串的每个字符"abc"映射到单个字符串(映射到["a", "b", "c"]),然后将所有结果字符串连接在一起(["a", "b", "c"]变为"abc").