Haskell类型检查/模式匹配

neb*_*ffa 1 haskell

下面的Haskell代码在最后一行抱怨,当我试图检查表达式是否符合形式为Cons _ _的东西时.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
Run Code Online (Sandbox Code Playgroud)

Vla*_*eev 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
Run Code Online (Sandbox Code Playgroud)

您使用警卫无效.您不能将函数(此处为(==)函数)应用于模式.也就是说,你无法比较(使用Eq类型类)某些东西Cons _ _.你需要再次模式匹配,它可以使用case .. of:

interpret_expr prog vars (Isnum expr) = case interpret_expr prog vars expr of
    Nil -> Num 0
    Cons _ _ -> Num 0
    _ -> Num 1
Run Code Online (Sandbox Code Playgroud)


Tho*_*son 5

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

isCons (Cons _ _) = True
isCons _          = False
Run Code Online (Sandbox Code Playgroud)

它将用作:

| isCons (interpret_expr prog vars expr) = Num 0
Run Code Online (Sandbox Code Playgroud)

这是很常见的,各种源到源重写工具将添加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)
Run Code Online (Sandbox Code Playgroud)