在Haskell中出现“含糊不清"的模棱两可的现象. [英] Ambiguous occurrence in Haskell with "show"

查看:142
本文介绍了在Haskell中出现“含糊不清"的模棱两可的现象.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是函数式编程的新手,我正在尝试使用Haskell创建和显示Stack.我希望我的程序向我展示我正在使用它构建的堆栈.这是我的代码:

I'm new in functional programming and I'm trying to create and show a Stack with Haskell. I'd like my program to show me the Stack I'm building with it. This is my code:

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)

如果使用显示(将1空)",我希望得到一个(或多或少)类似的答案:"1<-|" 但是我无法编译代码.当我尝试它时,显示以下错误:

With "show (push 1 empty)" I'd expect an answer (more or less) like: " 1 <- | " But I'm not able to compile the code. When I try it shows the following error:

[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.

我理解程序可能会使Prelude中的"show"与be定义的"show"混淆的错误,但是我在代码中看不到该错误.此外,一些队友具有相同的代码,并且该程序运行良好.

I understand the error where program could confuse the "show" from Prelude with an "show" defined by be, but I cannot see that error in my code. Besides, some mates have the same code, and the program works well.

有什么我需要改变还是错过了?

There is something I have to change or I have missed?

谢谢!

推荐答案

因此,第一个问题是您粘贴给我们的代码中有一个`字符.第二个问题是您不需要缩进模块中的所有行;我看到的大多数Haskell模块将 not 缩进模块的主体.您的第三个问题是,您不需要在show ashow b周围加上括号:Haskell中的优先级确实很简单.括号总是最高优先级,其次是函数应用程序(左联想或贪婪的nom",函数总是吞噬它在它前面看到的第一件事),其次是运算符,其定义的优先级是其后,然后是特殊的句法形式如\a ->letdowhere.这些通常是美学方面的问题,但您可能仍然会在意.

So the first problem is that you've got a ` character in the code you pasted for us. Your second problem is that you don't need to indent all of the lines in the module; most Haskell modules that I see will not indent the body of the module. Your third problem is that you do not need parentheses around show a and show b: precedence in Haskell is really simple; parentheses always take top priority, followed by function application (left-associative or "greedy nom", a function always gobbles up the first thing that it sees in front of it), followed by operators in their defined precedence, followed by special syntactic forms like \a ->, let, do, where. Those are generally aesthetic concerns but you probably still care.

您的最后一个问题在这里:

Your final problem is here:

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

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

You want Haskell to turn this into the single statement:

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

但是Haskell却将其分成了两行:

However Haskell has instead turned this into two separate lines:

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

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

因此,多重定义已正确转换为大小写分派,但没有放在上面的花括号中!因此,可以通过使用空格缩进线条来省略花括号{}.在where之后,Haskell没有看到任何显式的{},因此它开始查找缩进的行,并且看到其中的0,因此将子句转换为where {}(感谢@chi).

So the multiple-definition is correctly converted into a case-dispatch, but it's not put within the curly braces above! So, you can omit curly braces {} by using whitespace to indent lines. After where, Haskell does not see any explicit {} so it starts looking for indented lines, and it sees 0 of them, so it converts the clause to where {} (thanks @chi).

无论是否由于缩进而没有大括号,该新行定义了一个不同的功能Stack.show,与导入的Prelude.show属于Show类型类不同.问题在于它还引用了一个称为show的函数,该函数现在是模棱两可的:这是对具有无限类型show :: Stack (Stack (Stack ...)) -> String dispatching 的函数的递归调用吗?调用具有有限类型show :: (Show a) => Stack a -> String的函数?在它甚至试图弄清楚那些类型之前,它就说停止它,我不知道你的意思,请澄清."

Without being in curly braces, either because of indentation or not, that new line defines a different function, Stack.show, distinct from the imported Prelude.show that belongs to the Show typeclass. The problem is that it also references a function called show, which is now ambiguous: is this a recursive call for a function with infinite type show :: Stack (Stack (Stack ...)) -> String or a dispatching call for a function with finite type show :: (Show a) => Stack a -> String? Before it even tries to figure out those types it says "stop it, I don't know what you mean, please clarify."

可能您想要的是:

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

此缩进提示Haskell编译器接受where子句中的以下两个语句.

This indentation clues the Haskell compiler to accepti the two following statements into the where clause.

这篇关于在Haskell中出现“含糊不清"的模棱两可的现象.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆