这个函数的正确签名是什么?

此代码无法编译并出现此错误

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.`,那么必须列出该类型中的所有类型变量

以上是这个函数的正确签名是什么?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>