此代码无法编译并出现此错误
src/JsonParser.hs:33:37-62: error:
* Couldn't match type `b1' with `b'
`b1' is a rigid type variable bound by
the type signature for:
resultantRunParse :: forall b1. String -> Maybe (String, b1)
at src/JsonParser.hs:29:5-52
`b' is a rigid type variable bound by
the type signature for:
fmap :: forall a b. (a -> b) -> Parser a -> Parser b
at src/JsonParser.hs:27:11-42
Expected type: Maybe (String, b1)
Actual type: Maybe (String, b)
代码:
import Prelude
newtype Parser a = Parser
{ runParser :: String -> Maybe (String, a)
}
instance Functor Parser where
fmap :: (a -> b) -> Parser a -> Parser b
fmap f (Parser p) = Parser resultantRunParse where
-- THIS FUNCTION TYPE DECLARATION IS THE PROBLEM
-- IF I REMOVE THE TYPE DECLARATION, IT WORKS
resultantRunParse :: String -> Maybe (String, b)
resultantRunParse input =
case p input of
Nothing -> Nothing
Just (remaining, parsed) -> Just (remaining, f parsed)
我尝试了签名 resultantRunParse::forall b1。错误消息中建议的 String -> Maybe (String, b1)
也没有用。
此外,制作 resultantRunParse = undefined
并保持类型签名也有效。很奇怪!
这个函数的正确签名是什么?
最佳答案
类型签名必须包含b
,但它必须与封闭函数中使用的b
相同。如果没有作用域类型变量,这是不可能的:
https://wiki.haskell.org/Scoped_type_variables
为此,请在文件顶部添加评论:
{-# LANGUAGE ScopedTypeVariables #-}
然后,在封闭函数的类型签名中使用显式 forall b.
。
如果没有作用域类型变量,就无法在类型签名中写入 b
并使其与使用的相同 b
在封闭函数中。
(我个人的建议是不要在这里使用类型签名。这是没有必要的。)
关于haskell - 此功能的正确签名是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68248606/