如何在Haskell中打印Nothing

时间:2013-09-17 19:43:28

标签: haskell

我正在尝试编写一个返回列表中第一项的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

2 个答案:

答案 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 []

有趣的是,GHCi比GHC更具侵略性。这意味着

 :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 Boolprint (h [])工作!