1

当我试图检查表达式的计算结果是否为 Cons _ _ 形式时,以下 Haskell 代码在最后第二行抱怨。Haskell 的错误消息是:“表达式上下文中的模式语法:_” - 我想知道的是 - 有没有办法完成我想要做的事情???看来我要做的是在运行时检查表达式的类型,从我所读的内容来看,这可能意味着我可以更好地编程?但是,由于我是初学者,我不知道这是否是我正在做的事情,尤其是因为我在过去一个小时内一直在尝试这样做。

data Val = Num Int | Nil | Cons Val Val
    deriving (Eq, Show, Read)

interpret_expr :: Prog -> Vars -> Expr -> Val
interpret_expr _ _ (Isnum NilE) = Num 0
interpret_expr _ _ (Isnum (ConsE _ _)) = Num 0
interpret_expr _ _ (Isnum (NumE _)) = Num 1
interpret_expr prog vars (Isnum expr)
    | interpret_expr prog vars expr == Nil = Num 0
    | interpret_expr prog vars expr == Cons _ _ = Num 0
    | otherwise = Num 1
4

2 回答 2

8
interpret_expr prog vars (Isnum expr)
    | interpret_expr prog vars expr == Nil = Num 0
    | interpret_expr prog vars expr == Cons _ _ = Num 0
    | otherwise = Num 1

您对警卫的使用无效。您不能将函数(这里是(==)函数)应用于模式。也就是说,您无法比较(使用Eqtypeclass)某些东西和Cons _ _. 您需要再次进行模式匹配,可以使用case .. of

interpret_expr prog vars (Isnum expr) = case interpret_expr prog vars expr of
    Nil -> Num 0
    Cons _ _ -> Num 0
    _ -> Num 1
于 2013-04-11T05:59:04.467 回答
5

检查值是否属于特定构造函数是很常见的事情。很多时候你会在表单中看到一个手写的片段:

isCons (Cons _ _) = True
isCons _          = False

它将被用作:

| isCons (interpret_expr prog vars expr) = Num 0

这很常见,以至于各种源到源重写工具将添加is[Some Constructor]功能(例如:deriveDriFT)。我偏爱模板 haskell 解决方案(因为它们不需要运行外部工具,而不是因为 TH 非常干净或稳定)。如果您安装该derive库,那么您的代码可能如下所示:

import Data.Derive.Is
import Data.DeriveTH
import Language.Haskell.TH

data Val = ...
  deriving (Eq, Ord, Show)

$(derive makeIs ''Val)
于 2013-04-11T05:49:11.873 回答