我有这段代码:
type Variable = String
data Expr = T | Var Variable | And Expr Expr | Not Expr
测试用例如下:
prop_v1 = v (Not (And (Var "y") T)) === ["y"]
data Expr
的含义是什么 - 它只是定义了可以输入的类型及其参数吗?即Var
需要Variable
,And
需要两个Expr
。
答案 0 :(得分:10)
Expr
的数据类型声明系统地产生了一组模式,这些模式涵盖Expr
类型的值 的所有可能事物。我们来做翻译
data Expr -- any e :: Expr must be one of
= T -- T
| Var Variable -- (Var x) -- where x :: Variable
| And Expr Expr -- (And e1 e2) -- where e1 :: Expr, e2 :: Expr
| Not Expr -- (Not e1) -- where e1 :: Expr
您可以看到,每个T
子句的Var
,And
,Not
和data
都是构造函数 ,生活在价值语言中;每个子句中的其余部分都使用类型语言,说明Expr
的每个组件必须具有的类型。每个相应的模式由应用于模式变量的构造函数组成,代表具有给定类型的组件。基本上,函数左侧显示的模式是通过重复地将模式变量细化到它们的值可能采用的模式,,如其类型所示。
通过模式匹配编写函数不包括说做什么:它包括说输出是什么输入的可能情况>是。您需要将输入分析到可以轻松说出输出必须是什么的情况。所以,从一个一般情况开始......
v :: Expr -> [Variable]
v e = undefined
......并完善它。问“你能说出它到底是什么吗?”。我们无法在不了解v e
的情况下了解e
是什么。所以我们最好拆分 e。我们知道e :: Expr
,所以我们知道它的值可以匹配的模式。制作程序行的四个副本,并在每个程序行中将e
替换为上面列出的四种可能模式之一。
v :: Expr -> [Variable]
v T = undefined
v (Var x) = undefined
v (And e1 e2) = undefined
v (Not e1) = undefined
现在,在每种情况下,你能说出输出是什么吗?方便的是你可以在组件上使用递归调用。假设您在尝试说明vars e1
必须是什么时,您已经知道vars e2
和v (And e1 e2)
是什么。如果你正确的步骤,程序将是正确的。
我发现从具体的例子来考虑通常是有帮助的。以你的测试为例。
v (Not (And (Var "y") T))
那应该是["y"]
,对吧?它匹配哪种模式?
Not e1 -- with e1 = And (Var "y") T
什么
v e1
?看着它,最好是
["y"]
在此示例中,v (Not e1)
的{{1}}是什么?同样的。这可能会建议一个合适的表达式来替换
v e1
undefined
(当然,一个暗示性的例子只是一个好的开始,而不是正确性的保证。)
外卖消息:(1)通过分割模式变量来构建模式,通过查看类型的声明来确定可能的模式; (2)假设对组件的递归调用给出了正确的答案,然后尝试为整个问题构建正确的答案。
无耻的插件:shplit是我为学生构建的一个简单工具,可以机械地捕获消息(1)。
答案 1 :(得分:5)
data Expr
定义了一种新的数据类型,指定了Var
之类的“构造函数”,其中Variable
或And
采用两个表达式。
您可以使用以下构造函数与Expr
进行匹配:
fn (Var name) = ...
fn (And exp1 exp2) = ...
...
请注意,data Expr = ...
仅定义一个类型Expr
。 Var
,And
...等都是Expr
的构造函数,因此Var "blarg"
之类的值将属于Expr
类型
你应该阅读Learn You a Haskell的前几章来学习基础知识。
答案 2 :(得分:2)
另外,我如何用模式定义这个函数 匹配?
对不起,这是错误的问题。 这就像有人问“我如何通过数组索引处理矩阵乘法?” (对于哪一个人可以简单回复:为什么,你怎么做没有数组索引?)
你应该问“给定一个Expr,我怎样才能找到它中出现的所有变量?”然后,模式匹配的含义会自动展开。
您的数据类型Expr
是相当简单的布尔表达式的一种可能表示。你有变量,一个字面值T
(代表true
也许 - 顺便说一句,你确定你没有忘记F
吗?)并且如果 x 是一个表达式然后是Not
x ,如果 x 和 y 是表达式,那么{{ 1}} xy 。
所以,首先,请准确描述(不仅仅是:“我从左到右依次写下我找到的每个变量名称。”)如何在母语中找到这样一个表达式中的所有变量。例如:“如果表达式为And
,则该表达式中出现的变量列表为空。”务必涵盖所有可能的情况。然后回来,我们将向您展示如何将其转换为Haskell,但我相信到那时您会注意到它。