所以我正在编写一个程序,它返回一个给定算术问题的过程,所以我想要实现一些Show函数,以便我可以打印我测试时评估的相同表达式。问题是给定的代码与第一行匹配时( - )应该落到第二行。
{-# OPTIONS_GHC -XFlexibleInstances #-}
instance Show (t -> t-> t) where
show (+) = "plus"
show (-) = "minus"
main = print [(+),(-)]
返回
[plus,plus]
我是刚刚首先承担了致命的印刷功能,还是有某种方法可以让它与之匹配得恰到好处?
编辑:我意识到我收到了以下警告:
Warning: Pattern match(es) are overlapped
In the definition of `show': show - = ...
我仍然不知道为什么会重叠,或者如何阻止它。
答案 0 :(得分:9)
这是一种思考这个问题的方法。考虑:
answer = 42
magic = 3
specialName :: Int -> String
specialName answer = "the answer to the ultimate question"
specialName magic = "the magic number"
specialName x = "just plain ol' " ++ show x
你能明白为什么这不起作用吗?模式匹配中的answer
是一个变量,与外部范围的answer
不同。所以相反,你必须这样写:
answer = 42
magic = 3
specialName :: Int -> String
specialName x | x == answer = "the answer to the ultimate question"
specialName x | x == magic = "the magic number"
specialName x = "just plain ol' " ++ show x
实际上,这就是在模式中编写常量时正在发生的事情。那就是:
digitName :: Bool -> String
digitName 0 = "zero"
digitName 1 = "one"
digitName _ = "math is hard"
由编译器转换为等效于:
的东西digitName :: Bool -> String
digitName x | x == 0 = "zero"
digitName x | x == 1 = "one"
digitName _ = "math is hard"
由于您希望匹配绑定到(+)
的函数而不是将任何内容绑定到符号(+)
,因此您需要将代码编写为:
instance Show (t -> t-> t) where
show f | f == (+) = "plus"
show f | f == (-) = "minus"
但是,这需要功能在平等性方面具有可比性。这一般是一个不可判定的问题。
你可能会反驳说你只是要求运行时系统比较函数指针,但在语言层面,Haskell程序员无法访问指针。换句话说,您不能在Haskell(*)中操作对值的引用,只能自己赋值。这是Haskell的纯度,并获得参考透明度。
(*)MVar
和IO
monad中的其他此类对象是另一回事,但它们的存在不会使该点无效。
答案 1 :(得分:9)
正如 sepp2k 和 MtnViewMark 所说,您不能对标识符的值进行模式匹配,只能在构造函数上进行模式匹配,在某些情况下,还要进行隐式相等性检查。因此,您的实例将任何参数绑定到标识符,在此过程中隐藏(+)
的外部定义。不幸的是,这意味着你要做的事情不会也不会有效。
要实现的目标的典型解决方案是使用适当的show
实例定义“算术表达式”代数数据类型。请注意,您可以使表达式本身成为Num
的实例,其中数字文字包含在“Literal”构造函数中,而(+)
之类的操作返回其参数以及操作的构造函数。这是一个快速,不完整的例子:
data Expression a = Literal a
| Sum (Expression a) (Expression a)
| Product (Expression a) (Expression a)
deriving (Eq, Ord, Show)
instance (Num a) => Num (Expression a) where
x + y = Sum x y
x * y = Product x y
fromInteger x = Literal (fromInteger x)
evaluate (Literal x) = x
evaluate (Sum x y) = evaluate x + evaluate y
evaluate (Product x y) = evaluate x * evaluate y
integer :: Integer
integer = (1 + 2) * 3 + 4
expr :: Expression Integer
expr = (1 + 2) * 3 + 4
在GHCi中尝试:
> integer
13
> evaluate expr
13
> expr
Sum (Product (Sum (Literal 1) (Literal 2)) (Literal 3)) (Literal 4)
答案 2 :(得分:6)
它重叠,因为它将(+)
简单地视为一个变量,这意味着在RHS上标识符+将绑定到您调用的函数上。
无法按照您想要的方式对功能进行模式匹配。
答案 3 :(得分:1)
用一个巨大的黑客来解决它。
instance (Num t) => Show (t -> t-> t) where
show op =
case (op 6 2) of
8 -> "plus"
4 -> "minus"
12 -> "times"
3 -> "divided"