data Player = User | COM deriving Eq
data Spot = JustA Player | None deriving Eq
instance Show Player where
show User = "X"
show COM = "O"
instance Show Spot where
show None = " "
在上面的代码中,我创建了两种数据类型:“Player”和“Spot”,即“Just Player”或“None”。 现在我能够
show JustA User
给出结果“X”,但这不起作用。我尝试了各种方法来使用实例,但它们对我不起作用。
给出的错误是:
ghci> tictactoe
The computer will go first as O
| |
---+---+---
*** Exception: tictactoe.hs:11:5-19: Non-exhaustive patterns in function show
(尝试时出现错误
show JustA COM
)
问题不止一个。
错误信息
Non-exhaustive patterns in function show
告诉您有一个案例尚未处理。
GHC 可以告诉您,在编译时(或在 GHCi 中加载时),如果您打开 incomplete-patterns 标志:
ghci> :set -fwarn-incomplete-patterns
这样,您不仅会收到来自 GHCi 的警告,还会告诉您问题出在哪里:
Q77520101.hs:11:5: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for `show':
Patterns of type `Spot' not matched: JustA _
|
11 | show None = " "
| ^^^^^^^^^^^^^^^
不过,通常情况下,打开更广泛的标志集会更容易,其中包括
incomplete-patterns
:Wall。
要解决该问题,请将缺失的案例添加到
Spot
的 show
实例中:
instance Show Spot where
show None = " "
show (JustA p) = "JustA " ++ show p
尽管如此,让编译器派生
show
实例会更容易:
data Player = User | COM deriving (Eq, Show)
data Spot = JustA Player | None deriving (Eq, Show)
虽然,当然,这不会给你完全相同的输出。通过这种替代方案,
show User
将返回 User
而不是 X
。然而,这被认为是惯用的。
另一个问题可能与表达
show JustA User
有关。如果您在 GHCi 中尝试,它会给您详细的错误消息:
ghci> show JustA User
<interactive>:2:1: error:
* Couldn't match expected type: Player -> t
with actual type: [Char]
* The function `show' is applied to two value arguments,
but its type `(Player -> Spot) -> [Char]' has only one
In the expression: show JustA User
In an equation for `it': it = show JustA User
* Relevant bindings include it :: t (bound at <interactive>:2:1)
函数
show
需要一个单个输入值,但由于Haskell的语法,像show JustA User
这样的表达式对于Haskell编译器来说就像带有两个参数的函数调用。
您至少可以通过两种方式解决这个问题:
ghci> show (JustA User)
"JustA X"
ghci> show $ JustA User
"JustA X"
这两种替代方案使用不同的语法,但它们是等效的。无论您使用其中一种还是另一种,都是一个偏好问题。