如何在Haskell中打印Nothing

wan*_*nik 5 haskell

我正在尝试编写一个返回列表中第一项的Haskell函数.

h [] = Nothing
h (x:xs) = x
Run Code Online (Sandbox Code Playgroud)

当我用空列表调用它时:

main = print (h [])
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

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 [])
Run Code Online (Sandbox Code Playgroud)

当我给函数列出空列表时,我希望结果为Nothing.

Dan*_*zer 16

这里有一些问题,让我们首先添加一个合理的类型签名

h :: [a] -> Maybe a
h [] = Nothing
h (x:xs) = x
Run Code Online (Sandbox Code Playgroud)

现在我们得到一个错误,我们返回一个平原,x所以x需要类型Maybe a.我们可能不希望这样,所以我们将它包装在Just构造函数中

h (x:_) = Just x
Run Code Online (Sandbox Code Playgroud)

现在问你的问题.

请注意,这不是特定于您的功能,结果

main = print $ head []
main = print $ id []
main = print $ tail []
Run Code Online (Sandbox Code Playgroud)

都是一样的.

类型[][a].由于我们没有指定什么a类型h []Show a => Maybe a.额外的内容Show是因为我们想要打印我们的结果.但我们实际上并没有说明aGHC因为无法违约而感到愤怒.

有两种方法可以解决它,愚蠢的方法是使h单形(单态化?)h

h :: [Int] -> Maybe Int -- Bad
Run Code Online (Sandbox Code Playgroud)

更智能的方法是在我们的呼叫站点简单地选择具体类型.

main = print $ h ([] :: [Int])
Run Code Online (Sandbox Code Playgroud)

我选择Int没有特别的原因,这并不重要.现在Maybe Int是可打印的,所以我们都准备好了.该::语法的工作原理相同,因为它确实为顶级组件,只是声明的类型[]在我们的表达[Int].

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

 main = print []
Run Code Online (Sandbox Code Playgroud)

在GHCi中是合法的,但在GHC中则不合法.如果您遇到了有趣的行为,请询问表达式的类型以查看默认值

 :t []
Run Code Online (Sandbox Code Playgroud)