omi*_*nes 7 constructor haskell programming-languages pattern-matching
如果我们有类型Person定义如下:
--datatype in record syntax
data Person = Male { firstName :: String, lastName :: String } |
Female { firstName :: String, lastName :: String }
Run Code Online (Sandbox Code Playgroud)
可以这样:
flipNames :: Person -> Person
flipNames p@(Male{}) = Male (lastName p) (firstName p)
flipNames p@(Female{}) = Female (lastName p) (firstName p)
Run Code Online (Sandbox Code Playgroud)
写作flipNames的一个定义?我们能以某种方式捕获使用的构造函数,并将其重用于不同的参数吗?就像是:
flipNames (constructor fname lname) = c lname fname
Run Code Online (Sandbox Code Playgroud)
Nik*_*kov 11
虽然Ganesh已回答了您的确切问题,但我想说您的问题只是表明设计数据类型的方法不正确.
以下方法更灵活,可以解决您的问题:
data Person = Person { gender :: Gender, firstName :: String, lastName :: String }
data Gender = Male | Female
flipNames (Person gender firstName lastName) = Person gender lastName firstName
Run Code Online (Sandbox Code Playgroud)
这背后的规则非常简单:每当你看到自己创建具有相同字段的多个构造函数时,只需使用单个构造函数并引入另一个具有枚举类型的字段,如上面的代码所示.
你不会丢失任何模式匹配功能,因为模式可以是这样Person Male firstName lastName,并且你将能够使Gender类型派生Enum,Bounded并且肯定会帮助你获得不那么微不足道的类型.例如:
data Gender = Male | Female deriving (Enum, Bounded)
allGenders :: [Gender]
allGenders = enumFrom minBound
maidenName :: Person -> Maybe String
maidenName (Person Female _ z) = Just z
maidenName _ = Nothing
Run Code Online (Sandbox Code Playgroud)
在这种特殊情况下,您可以这样做:
flipNames :: Person -> Person
flipNames p = p { firstName = lastName p , lastName = firstName p }
Run Code Online (Sandbox Code Playgroud)
但是这只能起作用,因为记录选择器是Male和Female相同的.没有一般抽象可以捕获没有参数的构造函数.