繁体   English   中英

如何使用没有案例的警卫重写这个Haskell?

[英]How can I rewrite this Haskell using guards with no case-of?

我有三个版本的功能,如下所示。 #2和#3工作。 #2现在是我的第一选择。 我想找到一些让#1工作的方法,看看它是如何比较的。 它在底部。

首先,我有这种类型:

data Value =
    IntVal Int
  | BoolVal Bool
  deriving (Show)

而这个(工作片段)功能:

-- #2
evaluate (If ec et ef) s0 =
  case vc of
    (IntVal ____) -> error "Conditional expression in If statement must be a boolean" 
    (BoolVal vcb) -> if vcb then (vt, st)
                            else (vf, sf)
  where (vc, sc) = evaluate ec s0
        (vt, st) = evaluate et sc
        (vf, sf) = evaluate ef sc

我想知道我是否可以摆脱案件陈述并使用警卫代替。 我可以使用case语句后卫,我发现这工作:

-- #3
evaluate (If ec et ef) s0 =
  case vc of
    (IntVal _) -> error "Conditional expression in If statement must be a boolean" 
    (BoolVal vcb) | vcb       -> (vt, st)
                  | otherwise -> (vf, sf)
  where (vc, sc) = evaluate ec s0
        (vt, st) = evaluate et sc
        (vf, sf) = evaluate ef sc

很高兴知道。 我认为#2最清楚地传达了我的意图。 尽管如此,这是我尝试的第一件事,我想弄清楚它是如何实际工作的:

-- #1
evaluate (If ec et ef) s0 
  | (IntVal vc) = error "Conditional expression in If statement must be a boolean" 
  | vc == True  = (vt, st)
  | otherwise   = (vf, sf)
  where (vc, sc) = evaluate ec s0
        (vt, st) = evaluate et sc
        (vf, sf) = evaluate ef sc

这给出了以下错误。 似乎我需要一些东西来询问Value类型的某些东西是否也是IntVal子类型的东西?:

Couldn't match expected type `Int' with actual type `Value'
In the first argument of `IntVal', namely `vc'
In the expression: (IntVal vc)

--------------------------------------------------------------------------------

Couldn't match expected type `Bool' with actual type `Value'
In the expression: (IntVal vc)
In a stmt of a pattern guard for
               an equation for `evaluate':
  (IntVal vc)

如何解决这些错误并实现无案例,仅限警卫的实施?

这不是一个真正的答案,但我会写下这样的事情:

evaluate (If ec et ef) s0 =
    case evaluate ec s0 of
    (True,  sc) -> evaluate et sc
    (False, sc) -> evaluate ef sc

我发现vtstvfsf的命名更难以阅读,因为我必须自己跟踪这些变量的数据流。 保持他们的匿名简化了理解。

你的#1的问题在于,普通的守卫只能是布尔表达式,它们无法简洁地匹配模式。 所以IntVal vc就不会像一个人一样工作。 而且即使这样做了, vc你从得到IntVal vc模式不能被用作一个Bool值-你需要的BoolVal vc该模式。

但是,您可以使用图案保护

evaluate (If ec et ef) s0
  | IntVal _      <- vc = error "Conditional expression in If statement must be a boolean" 
  | BoolVal True  <- vc = (vt, st)
  | BoolVal False <- vc = (vf, sf)
  where (vc, sc) = evaluate ec s0
        (vt, st) = evaluate et sc
        (vf, sf) = evaluate ef sc

如果使用记录语法重新定义类型Value

data Value = IntVal { unInt :: Int } | BoolVal { unBool :: Bool }

然后你可以这样做:

evaluate (If ec et ef) s0 =
  if unBool vc then (vt, st) else (vf, sf)
  where (vc, sc) = evaluate ec s0
        (vt, st) = evaluate et sc
        (vf, sf) = evaluate ef sc

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM