这个函数的正确签名是什么?
此代码无法编译并出现此错误
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。
(我个人的建议是不要在这里使用类型签名。没有必要。)
- 你需要量化两者,GHC 有一个 [`forall`-or-nothing 规则](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/explicit_forall.html#the-forall-or-无规则):如果一个类型有一个最外层的显式`forall.`,那么必须列出该类型中的所有类型变量