在 Haskell 和 "show" 中出现歧义
Ambiguous occurrence in Haskell with "show"
我是函数式编程的新手,我正在尝试使用 Haskell 创建和显示堆栈。我希望我的程序能够向我展示我正在使用它构建的 Stack。这是我的代码:
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)
对于 "show (push 1 empty)",我希望得到这样的答案(或多或少):“ 1 <- | ”
但是我无法编译代码。当我尝试时,它显示以下错误:
[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" 混淆的错误,但我在我的代码中看不到该错误。另外,有小伙伴代码相同,程序运行良好
有什么我必须改变或者我错过了什么?
谢谢!
所以第一个问题是您在为我们粘贴的代码中有一个 `
字符。您的第二个问题是您不需要缩进模块中的所有行;我看到的大多数 Haskell 模块 不会 缩进模块的主体。您的第三个问题是您不需要 show a
和 show b
周围的括号:Haskell 中的优先级非常简单;括号始终具有最高优先级,其次是函数应用程序(left-associative 或 "greedy nom",函数总是吞噬它在其前面看到的第一件事),然后是定义优先级的运算符,然后是特殊句法形式,如 \a ->
、let
、do
、where
。这些通常是审美问题,但您可能仍然关心。
你的最后一个问题在这里:
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 }
所以 multiple-definition 被正确转换为 case-dispatch,但它没有放在上面的花括号内!因此,您可以通过使用空格缩进行来省略花括号 {}
。在 where
之后,Haskell 没有看到任何明确的 {}
所以它开始寻找缩进行,它看到了 0 个,所以它将子句转换为 where {}
(感谢@chi)。
没有在大括号中,无论是否因为缩进,新行定义了一个不同的函数,Stack.show
,不同于属于 Show
的导入的 Prelude.show
类型类。问题在于它还引用了一个名为 show
的函数,该函数现在是模棱两可的:这是一个 递归 调用具有无限类型 show :: Stack (Stack (Stack ...)) -> String
的函数还是 调度 调用有限类型的函数show :: (Show a) => Stack a -> String
?在它试图找出这些类型之前,它会说 "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
子句中。
我是函数式编程的新手,我正在尝试使用 Haskell 创建和显示堆栈。我希望我的程序能够向我展示我正在使用它构建的 Stack。这是我的代码:
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)
对于 "show (push 1 empty)",我希望得到这样的答案(或多或少):“ 1 <- | ” 但是我无法编译代码。当我尝试时,它显示以下错误:
[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" 混淆的错误,但我在我的代码中看不到该错误。另外,有小伙伴代码相同,程序运行良好
有什么我必须改变或者我错过了什么?
谢谢!
所以第一个问题是您在为我们粘贴的代码中有一个 `
字符。您的第二个问题是您不需要缩进模块中的所有行;我看到的大多数 Haskell 模块 不会 缩进模块的主体。您的第三个问题是您不需要 show a
和 show b
周围的括号:Haskell 中的优先级非常简单;括号始终具有最高优先级,其次是函数应用程序(left-associative 或 "greedy nom",函数总是吞噬它在其前面看到的第一件事),然后是定义优先级的运算符,然后是特殊句法形式,如 \a ->
、let
、do
、where
。这些通常是审美问题,但您可能仍然关心。
你的最后一个问题在这里:
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 }
所以 multiple-definition 被正确转换为 case-dispatch,但它没有放在上面的花括号内!因此,您可以通过使用空格缩进行来省略花括号 {}
。在 where
之后,Haskell 没有看到任何明确的 {}
所以它开始寻找缩进行,它看到了 0 个,所以它将子句转换为 where {}
(感谢@chi)。
没有在大括号中,无论是否因为缩进,新行定义了一个不同的函数,Stack.show
,不同于属于 Show
的导入的 Prelude.show
类型类。问题在于它还引用了一个名为 show
的函数,该函数现在是模棱两可的:这是一个 递归 调用具有无限类型 show :: Stack (Stack (Stack ...)) -> String
的函数还是 调度 调用有限类型的函数show :: (Show a) => Stack a -> String
?在它试图找出这些类型之前,它会说 "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
子句中。