j-a*_*j-a 5 haskell pattern-guards
根据这些定义,学习Haskell并且我不确定为什么我没有得到预期的结果:
instance Ring Integer where
addId = 0
addInv = negate
mulId = 1
add = (+)
mul = (*)
class Ring a where
addId :: a -- additive identity
addInv :: a -> a -- additive inverse
mulId :: a -- multiplicative identity
add :: a -> a -> a -- addition
mul :: a -> a -> a -- multiplication
Run Code Online (Sandbox Code Playgroud)
我写了这个函数
squashMul :: (Ring a) => RingExpr a -> RingExpr a -> RingExpr a
squashMul x y
| (Lit mulId) <- x = y
| (Lit mulId) <- y = x
squashMul x y = Mul x y
Run Code Online (Sandbox Code Playgroud)
然而:
*HW05> squashMul (Lit 5) (Lit 1)
Lit 1
Run Code Online (Sandbox Code Playgroud)
如果我专门为Integer编写一个版本:
squashMulInt :: RingExpr Integer -> RingExpr Integer -> RingExpr Integer
squashMulInt x y
| (Lit 1) <- x = y
| (Lit 1) <- y = x
squashMulInt x y = Mul x y
Run Code Online (Sandbox Code Playgroud)
然后我得到了预期的结果.
(Lit mulId) <- x即使x不是(点亮1),为什么匹配?
模式匹配中使用的变量被认为是局部变量.考虑这个定义来计算列表的长度:
len (x:xs) = 1 + len xs
len _ = 0
Run Code Online (Sandbox Code Playgroud)
变量x和xs是局部变量这个定义.特别是,如果我们为顶级变量添加定义,如
x = 10
len (x:xs) = 1 + len xs
len _ = 0
Run Code Online (Sandbox Code Playgroud)
这并不会影响它们的含义len.更详细地,所述第一图案(x:xs)是不等同于(10:xs).如果它以这种方式解释,我们现在可以len [5,6] == 0打破以前的代码!幸运的是,模式匹配的语义对于这样的新声明是健壮的x=10.
你的代码
squashMul :: (Ring a) => RingExpr a -> RingExpr a -> RingExpr a
squashMul x y
| (Lit mulId) <- x = y
| (Lit mulId) <- y = x
squashMul x y = Mul x y
Run Code Online (Sandbox Code Playgroud)
实际意味着
squashMul :: (Ring a) => RingExpr a -> RingExpr a -> RingExpr a
squashMul x y
| (Lit w) <- x = y
| (Lit w) <- y = x
squashMul x y = Mul x y
Run Code Online (Sandbox Code Playgroud)
这是错误的,因为w可以是任意的.你想要的可能是:
squashMul :: (Eq a, Ring a) => RingExpr a -> RingExpr a -> RingExpr a
squashMul x y
| (Lit w) <- x , w == mulId = y
| (Lit w) <- y , w == mulId = x
squashMul x y = Mul x y
Run Code Online (Sandbox Code Playgroud)
(Eq a约束可能取决于RingExpr未发布的定义)
您还可以将所有内容简化为:
squashMul :: (Eq a, Ring a) => RingExpr a -> RingExpr a -> RingExpr a
squashMul x@(Lit w) y | w == mulId = y
squashMul x y@(Lit w) | w == mulId = x
squashMul x y = Mul x y
Run Code Online (Sandbox Code Playgroud)
甚至:
squashMul :: (Eq a, Ring a) => RingExpr a -> RingExpr a -> RingExpr a
squashMul (Lit w) y | w == mulId = y
squashMul x (Lit w) | w == mulId = x
squashMul x y = Mul x y
Run Code Online (Sandbox Code Playgroud)
这个版本甚至不使用模式保护,因为没有必要.
| 归档时间: |
|
| 查看次数: |
117 次 |
| 最近记录: |