为什么在定义实例时会出现模糊的出现错误?

Zet*_*eta 3 syntax haskell typeclass

我有一个类型,Foo并希望使它成为一个实例Show,以便我可以在GHCi中使用它:

data Foo = Foo

instance Show Foo where
show Foo = "Foo"
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试使用它时,出现了一个模糊的错误:

ghci> show Foo
<interactive>:4:1:
    Ambiguous occurrence `show'
    It could refer to either `Main.show', defined at Foo.hs:4:1
                          or `Prelude.show',
                             imported from `Prelude' at Foo.hs:1:1
                             (and originally defined in `GHC.Show')
Run Code Online (Sandbox Code Playgroud)

为什么?我刚刚定义了属于类型类的函数,不是吗?

Zet*_*eta 6

TL; DR:缩进您的实例绑定.


启用警告,您会注意到您没有实现实例操作 show,而是使用具有相同名称的函数:

Foo.hs:3:10: Warning:
    No explicit implementation for
      either `showsPrec' or `Prelude.show'
    In the instance declaration for `Show Foo'
Run Code Online (Sandbox Code Playgroud)

因此现在有两个show.Main.show(你刚刚意外定义的Prelude.show那个)和(你想要使用的那个类).

我们可以通过查看他们的类型来验证(虽然我们需要完全限定他们的名字):

ghci> :t Main.show
Main.show :: Foo -> [Char]
ghci> :t Prelude.show
Prelude.show :: Show a => a -> String
Run Code Online (Sandbox Code Playgroud)

那是因为你的where绑定需要缩进,就像你在普通函数中缩进它们一样.即使只有一个空间就足够了:

instance Show Foo where
 show Foo = "Foo"
Run Code Online (Sandbox Code Playgroud)

请记住,Haskell使用空格来分隔块.只要问问自己:什么时候会where停止?