假设我使用记录语法定义了如下数据类型Person
:
data Person = Person { name :: String
, age :: Int
} deriving (Show)
我使用以下方法实例化Person
的列表:
people = [Person {name="Alice", age=27},
Person {name="Bob", age=23},
Person {name="Mallory", age=26}]
然后我意识到,一次定义列表中的许多元素会很笨重,因为重复了name
和age
这两个词。因此我将代码缩减为:
people = [(Person "Alice" 27),
(Person "Bob" 23),
(Person "Mallory" 26)]
由于Haskell中的列表无论如何都是同质的,我怎样才能避免在列表的每个元素中指定类型Person
?例如,按照以下代码(不编译)执行某些操作:
Person people = [("Alice" 27),
("Bob" 23),
("Mallory" 26)]
答案 0 :(得分:7)
Person
,作为数据值的构造函数,本身就是一个(二进制)函数。您可以从元组列表中构建此列表:
people = map (uncurry Person) [("Alice", 27), ("Bob", 42)]
或者您可以从名单和年龄列表中构建它:
people = zipWith Person ["Alice", "Bob"] [27, 42]
......或者来自其他许多选择。
答案 1 :(得分:3)
笑话回答:
instance Enum Person where
toEnum i = Person (show i) i
fromEnum (Person _ i) = i
personList :: [Person]
personList = [toEnum 0..]
还是一个笑话答案:
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE OverloadedStrings #-}
import Data.String
instance IsString Person where
fromString ps =
let (name,read . drop 1 -> age) = break (==':') ps
in Person name age
personList :: [Person]
personList = ["Me:30"
,"Them:55"
]
扭曲的笑话回答:
{-# LANGUAGE FlexibleInstances#-}
{-# LANGUAGE OverloadedStrings #-}
import Data.String
instance IsString (Int -> Person) where
fromString = Person
data Person = Person { name :: String
, age :: Int
} deriving (Show)
($$) :: (Int -> Person) -> Int -> Person
($$) = ($)
persons :: [Person]
persons = ["Me" $$ 30, "Them" $$ 55]
评论答案:
personList = map (uncurry Person) [("Me",30), ("Them", 55)]
错误的答案:
personList = zipWith Person ["Me", "Them"] [30,55]
答案 2 :(得分:1)
在Haskell中,人们往往不需要很多代表大量的文字数据,所以我们可能会高兴的是语言没有针对它们的表示进行优化。以下是一些选项:
people = (
let p = Person in
[p "Alice" 27,
p "Bob" 23,
p "Mallory" 26]
)
或者使用一些基本的解析
people = (
let p x = p' (words x)
p' [name, age] = person name (read age) in
map p $ lines "Alice 27\nBob 23\n Mallory 26"
)
或者只是按照你喜欢的方式执行show people
,默认情况下会使用Haskell语法,所以只需将它放在源文件的底部并忘记它。