在Haskell中访问自定义数据类型的成员

35 haskell

假设我在Haskell中有以下自定义数据类型和函数:

data Person = Person { first_name :: String, 
                       last_name :: String,
                       age :: Int 
                     } deriving (Eq, Ord, Show)
Run Code Online (Sandbox Code Playgroud)

如果我想创建一个函数print_age来打印Person的年龄,就像这样:print_age (Person "John" "Smith" 21),如何编写print_age访问age参数?我是一个面向对象的人,所以我不在这里.我基本上在寻找相当于Person.age的东西.

Dan*_*her 52

函数应用程序是前缀,因此age person对应person.age()于OOP语言中的常见.该print_age功能可以通过功能组合物来限定pointfree

print_age = print . age
Run Code Online (Sandbox Code Playgroud)

或点满

print_age person = print (age person)
Run Code Online (Sandbox Code Playgroud)


huo*_*uon 18

这称为记录语法,LYAH有一个很好的部分(ctrl-f表示"记录语法").

当使用记录定义数据类型时,Haskell会自动定义与记录同名的函数作为访问者,因此在这种情况下age是age字段的访问者(它具有类型Person -> Int),并且类似于first_namelast_name.

这些是普通的Haskell函数,因此称为like age personfirst_name person.

  • 作为一个完全的(!)新手,我发现记录产生的命名空间混乱是丑陋和令人沮丧的。Frege 语法很有吸引力,而且 iiuc 避免了这个问题。 (2认同)

Dan*_*ner 9

除了age其他答案中提到的功能之外,有时使用模式匹配也很方便.

print_age Person { age = a } = {- the a variable contains the person's age -}
Run Code Online (Sandbox Code Playgroud)

有一个非常无害的扩展,允许您跳过命名位:

{-# LANGUAGE NamedFieldPuns #-}
print_age Person { age } = {- the age variable contains the person's age -}
Run Code Online (Sandbox Code Playgroud)

...和另一个,由各种社区成员不同程度的不信任看待,这使你甚至可以跳过说明你想要带入哪些领域:

{-# LANGUAGE RecordWildCards #-}
print_age Person { .. } = {- first_name, last_name, and age are all defined -}
Run Code Online (Sandbox Code Playgroud)