想象一下,我有一个自定义类型和两个函数:
type MyType = Int -> Bool
f1 :: MyType -> Int
f3 :: MyType -> MyType -> MyType
我尝试按如下方式进行模式匹配:
f1 (f3 a b i) = 1
但它失败了,错误:Parse error in pattern: f1
。做上述事情的正确方法是什么?基本上,我想知道有多少f3(作为a和b可能是f3或其他一些功能)。
答案 0 :(得分:6)
您无法在功能上进行模式匹配。对于(几乎)任何给定的函数,有无数种方法来定义相同的函数。事实证明,在数学上,计算机始终无法确定给定的定义是否表达与另一个定义相同的功能。这也意味着Haskell无法可靠地判断函数是否与模式匹配;所以语言根本不允许。
模式必须 单个变量或应用于其他模式的构造函数。记住构造函数以大写字母开头,变量以小写字母开头,模式f3 a n i
无效;模式f3
的“头部”是变量,但它也适用于a
,n
和i
。这是你得到的错误信息。
由于函数没有构造函数,因此可以匹配函数的 only 模式是单个变量;匹配所有函数(无论如何都要传递给模式的正确类型)。这就是Haskell如何强制执行“无功能模式匹配”规则。基本上,在更高阶函数中,根本没有任何关于你已经给出的函数的信息,除了以将其应用于某事并看看它的作用。
函数f1
的类型为MyType -> Int
。这相当于(Int -> Bool) -> Int
。因此,需要类型为Int -> Bool
的单函数参数。我希望f1
的等式看起来像:
f1 f = ...
您不需要通过模式匹配来“检查”它是否是Int -> Bool
函数;类型保证它将是。
你不能告诉它是哪一个;但这通常是将函数作为参数的重点(这样调用者就可以选择任何函数,因为他们知道你将以同样的方式使用它们。)
我不确定你的意思是“我想知道有多少f3在那里”。 f1
始终会收到单个函数,而f3
根本不是要传递给f1
的正确类型的函数(它是MyType -> MyType -> MyType
},而不是MyType
)。
答案 1 :(得分:4)
一旦应用了一个函数,它的句法形式就会丢失。现在有办法,我应该{1}}为您提供区分2 + 3
的内容。它可以来自5
或2 + 3
,或仅仅是3 + 2
。
如果你需要捕获句法结构,那么你需要使用句法结构。
5
此处数据类型data Exp = I Int | Plus Exp Exp
justFive :: Exp
justFive = I 5
twoPlusThree :: Exp
twoPlusThree = I 2 `Plus` I 3
threePlusTwo :: Exp
threePlusTwo = I 2 `Plus` I 3
会捕获数字表达式,我们可以对它们进行模式匹配:
Exp
但是等等,为什么我要区分"构造函数"我可以模式匹配和...." 其他语法"哪个我不能?
基本上,构造函数是惰性的。 isTwoPlusThree :: Exp -> Bool
isTwoPlusThree (Plus (I 2) (I 3)) = True
isTwoPlusThree _ = False
的行为是......什么也不做,只是留在一个有两个名为" Plus x y
"并使用Plus _ _
和x
表示的值插入两个广告位。
另一方面,功能应用是最惰性的!将表达式应用于函数时,函数y
将使用应用值替换其正文中的(\x -> ...)
es。此动态缩减行为意味着无法获得"功能应用程序"。一看到它们就会消失在空气中。