use*_*304 4 haskell types functional-programming
考虑一个类型
data MyBool a = TRUE | FALSE
Run Code Online (Sandbox Code Playgroud)
请注意,MyBool a这并不真正取决于a,但让我们这样做只是为了好玩。
现在想象我想定义一个函数isParsable :: (Read a) => String -> MyBool a来决定给定的字符串是否可解析为a并将结果输出为MyBool a.
当然,我想写:
isParsable :: (Read a) => String -> MyBool a
isParsable str
| (null parses) = FALSE
| (otherwise) = TRUE
where parses = (reads str)::[(a, String)]
Run Code Online (Sandbox Code Playgroud)
现在这不能编译,但我真的不明白为什么。我不认为这个函数是模棱两可的,因为任何调用isParsable都必须强制选择a并因此确保Read a满足约束,因为它就在类型签名中。此外,该where条款强制reads :: String -> [(a, String)]. 但出于某种原因,GHC 抛出了一个错误。
我在这里误解了什么,有什么方法可以克服这个问题?
在标准 Haskell 中,a类型签名中的 与正文中的不同。为了使它们相同,您需要启用ScopedTypeVariables扩展并对其进行明确量化,如下所示:
{-# LANGUAGE ScopedTypeVariables #-}
data MyBool a = TRUE | FALSE
isParsable :: forall a. (Read a) => String -> MyBool a
isParsable str
| (null parses) = FALSE
| (otherwise) = TRUE
where parses = (reads str)::[(a, String)]
Run Code Online (Sandbox Code Playgroud)
如果你想在没有语言扩展的情况下做到这一点,你可以使用一个辅助函数,类似于为什么asTypeOf有用:
data MyBool a = TRUE | FALSE
isParsableHelper :: [(a, String)] -> MyBool a
isParsableHelper parses
| (null parses) = FALSE
| (otherwise) = TRUE
isParsable :: (Read a) => String -> MyBool a
isParsable str = (isParsableHelper parses)
where parses = (reads str)
Run Code Online (Sandbox Code Playgroud)