我希望用这种漂亮,干净的方式来描述具有函数和模式匹配的对象的属性:
data Animal = Cat | Dog | Cow
isBig :: Animal -> Bool
isLoyal :: Animal -> Bool
-- many more possible properties, including complicated non-bools, methods, and whatnot
--- Describing Cat
isBig Cat = False
isLoyal Cat = False
--- more properties
--- Describing Dog
isBig Dog = False
isLoyal Dog = True
--- more properties
--- Describing Cow
isBig Cow = True
isLoyal Cow = False
--- more properties
但是,这会产生有关多个声明的错误。因为,显然,通过模式匹配的函数定义必须在连续的行中完成。
这是否表明我的方法是错误的,不像Haskell一样?或者它只是语言中的一个缺陷?或者我误解了什么?
答案 0 :(得分:5)
这既不是语言中的缺陷,也不表明你的方法是错误的。这仅仅是一个句法限制,作为一个令人讨厌的设计决定的一部分,必须以某种方式做出。
限制的吸引力在于它意味着在阅读代码时,人们不必担心他们错过了部分值的定义,因为它分散在当前文件的远处。但它确实阻止了一些完美的逻辑组织代码方式,包括您当前正在尝试使用的方法。
我们不能同时拥有这两件事真是太可惜了!
可以考虑做这样的事情:
data Stats = Stats
{ isBig :: Bool
, isLoyal :: Bool
, -- ...
}
stats :: Animal -> Stats
stats Cat = Stats
{ isBig = False
, isLoyal = False
}
答案 1 :(得分:2)
引用Section 4.4.3.1 of the Haskell Report:
4.4.3.1功能绑定
函数绑定将变量绑定到函数值。变量x的函数绑定的一般形式是:
[函数绑定语法规范,涵盖多子句场景。]
请注意,定义函数的所有子句必须是连续的,并且每个子句中的模式数必须相同。 [...]
您注意到的限制是“定义函数的所有子句必须是连续的”。 Daniel Wagner的回答讨论了这一设计决策背后的可能原理。特别要强调的是,忘记与某个类型的构造函数相对应的子句是一个非常危险的错误,如果有可能以你建议的方式拆分条款,那么它将更容易实现(一个函数需要预计Animal
将处理所有三种可能性。