使用"显示"在Haskell中出现模糊不清的情况

时间:2016-01-06 14:24:59

标签: haskell ambiguous-call

我是函数式编程的新手,我尝试使用Haskell创建和显示Stack。我希望我的程序能够向我展示Stack I&#m; m with building。这是我的代码:

module Stack (Stack, empty, push, pop, top, isEmpty) where
    data Stack a       = EmptyStack | Stk a (Stack a)
    push x s           = Stk x s
    top (Stk x s)      = x
    pop (Stk _ s)      = s
    empty              = EmptyStack
    isEmpty EmptyStack = True
    isEmpty (Stk x s)  = False`

    instance Show a => Show (Stack a) where
    show EmptyStack = "|"
    show (Stk a b) = (show a) ++ " <- " ++ (show b)

用&#34;显示(按1空)&#34;我希望答案(或多或少)像:&#34; 1&lt; - | &#34; 但是我无法编译代码。当我尝试它时显​​示以下错误:

[1 of 1] Compiling Stack            ( Stack.hs, interpreted )

Stack.hs:12:27:
    Ambiguous occurrence ‘show’
    It could refer to either ‘Stack.show’, defined at Stack.hs:11:9
                      or ‘Prelude.show’,
                         imported from ‘Prelude’ at Stack.hs:1:8-12
                         (and originally defined in ‘GHC.Show’)

Stack.hs:12:47:
    Ambiguous occurrence ‘show’
    It could refer to either ‘Stack.show’, defined at Stack.hs:11:9
                      or ‘Prelude.show’,
                         imported from ‘Prelude’ at Stack.hs:1:8-12
                         (and originally defined in ‘GHC.Show’)
Failed, modules loaded: none.

我理解程序可能会混淆&#34; show&#34;来自Prelude的&#34; show&#34;由be定义,但我在代码中看不到该错误。此外,一些配偶具有相同的代码,程序运行良好。

我有什么需要改变或者我错过了吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

所以第一个问题是你为我们粘贴的代码中有一个`字符。你的第二个问题是你不需要缩进模块中的所有行;我看到的大多数Haskell模块将缩进模块的主体。你的第三个问题是你不需要在show ashow b附近使用括号:Haskell中的优先级非常简单;括号总是优先考虑,其次是函数应用程序(左关联或“贪婪的名词”,一个函数总是吞噬它在它前面看到的第一个东西),然后是运算符的定义优先级,接着是特殊的句法形式例如\a ->letdowhere。这些通常是美学问题,但你可能仍在关注。

你最后的问题在这里:

instance Show a => Show (Stack a) where
show EmptyStack = "|"
show (Stk a b) = (show a) ++ " <- " ++ (show b)

您希望Haskell将其转换为单个语句:

instance Show a => Show (Stack a) where show tmpvar = case tmpvar of { EmptyStack -> "|"; Stk a b -> show a ++ " <- " ++ show b }

然而,Haskell将其分为两个单独的行:

instance Show a => Show (Stack a) where {} 

show tmpvar = case tmpvar of { EmptyStack -> "|"; Stk a b -> show a ++ " <- " ++ show b }

所以多重定义被正确地转换为case-dispatch,但它并没有放在上面的花括号中!因此,您可以通过使用空格来缩进行来省略花括号{}。在where之后,Haskell看不到任何显式的{},所以它开始寻找缩进的行,并且它看到0,所以它将子句转换为where {}(感谢@chi)。

由于缩进与否,没有大括号,新行定义了一个不同的函数Stack.show,不同于属于Prelude.show类型类的导入的Show。问题是它还引用了一个名为show的函数,它现在是不明确的:这是对具有无限类型show :: Stack (Stack (Stack ...)) -> String调度的函数的递归调用调用有限类型show :: (Show a) => Stack a -> String的函数?在它甚至试图弄清楚那些类型之前它说“停止它,我不知道你的意思,请澄清。”

可能你想要的是:

instance Show a => Show (Stack a) where
    show EmptyStack = "|"
    show (Stk a b) = show a ++ " <- " ++ show b

此缩进提示Haskell编译器将以下两个语句加入where子句。