可以使用不同的参数集捕获和重用构造函数吗?

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)


GS *_*ica 5

在这种特殊情况下,您可以这样做:

flipNames :: Person -> Person
flipNames p = p { firstName = lastName p , lastName = firstName p }
Run Code Online (Sandbox Code Playgroud)

但是这只能起作用,因为记录选择器是MaleFemale相同的.没有一般抽象可以捕获没有参数的构造函数.