我正在尝试编写一个返回列表中第一项的Haskell函数。
h [] = Nothing
h (x:xs) = x
当我用空列表调用它时:
main = print (h [])
我收到以下错误:
prog.hs:4:8:
No instance for (Show a0) arising from a use of `print'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 23 others
In the expression: print (h [])
In an equation for `main': main = print (h [])
当我给函数提供空列表时,我希望结果为 Nothing 。
答案 0 :(得分:16)
这里有一些问题,让我们首先添加一个合理的类型签名
h :: [a] -> Maybe a
h [] = Nothing
h (x:xs) = x
现在我们收到了错误消息,我们正在返回普通x
,因此x
需要为Maybe a
类型。我们可能不希望这样,所以我们将它包装在Just
构造函数
h (x:_) = Just x
现在问题。
请注意,这不是特定于您的功能,
的结果main = print $ head []
main = print $ id []
main = print $ tail []
都是一样的。
[]
的类型为[a]
。由于我们未指定a
h []
的类型为Show a => Maybe a
Show
。额外的a
是因为我们想要打印我们的结果。但我们实际上并没有说h
是什么,所以GHC因为无法违约而感到恐惧。
有两种方法可以修复它,愚蠢的方法是将h
单态(单态化?)改为h :: [Int] -> Maybe Int -- Bad
main = print $ h ([] :: [Int])
更智能的方法是在我们的呼叫站点选择一种具体类型。
Int
我选择Maybe Int
没有特别的原因,这并不重要。现在::
是可打印的,所以我们都准备好了。 []
语法与顶层组件的工作方式相同,只是声明表达式中[Int]
的类型为 main = print []
。
:t []
在GHCi中是合法的,但在GHC中则不合法。如果你有一个有趣的行为,请询问表达式的类型,看看默认是什么
{{1}}
答案 1 :(得分:1)
编译器沉默你的功能
h [] = Nothing
h (x:xs) = x
但h
的类型为[Maybe a] -> Maybe a
,而非[a] -> Maybe a
。
h :: [a] -> Maybe a
h [] = Nothing
h (x:_) = Just x
[]
是多态类型[a]
,因此函数结果h []
,等于Nothig
仍然是多态类型Maybe a
,但print
可以不使用多态类型(如果我们没有Show
的实例)。在gchi中你可以运行
> print (h [])
但是这种情况gchi会将其转换为print ((h []) :: Maybe Int)
但是如果你的多态函数较少,比如:
h [] = Nothing
h (x:_) = Just $ x == ""
然后编译器找到它类型h :: [String] -> Maybe Bool
和print (h [])
工作!