根据类型从列表中提取值?

时间:2016-09-25 08:37:43

标签: haskell types

我试图迭代自定义数据类型列表,并确定特定类型的值。在这种情况下,我希望列表中的年龄

data MyData = Age Int | DOB Int | Name String | Address String

myList = [Age 89, DOB 13, Age 33, Name "Barbra", Address "103 Lane"]

myFunction :: [MyData] -> MyData
myFunction (x : xs) = if x == Age then x : myFunction xs else myFunction xs

错误:

"Age is applied to too few arguments"

对此最好的解决方案是什么?

1 个答案:

答案 0 :(得分:5)

你真的没有x == Age ......这没有意义。您只能将xMyData类型的其他值进行比较,例如Age 10DOB 40Name "John"Age没有MyData类型...它的类型为Int -> MyData

您可以使用case语句检查值的构造函数:

myFunction :: [MyData] -> MyData
myFunction (x:xs) = case x of
                      Age _     -> ...
                      DOB _     -> ...
                      Name _    -> ...
                      Address _ -> ...

或者,如果您只关心Age构造函数,则可以使用通配符:

myFunction :: [MyData] -> MyData
myFunction (x:xs) = case x of
                      Age _ -> ...
                      _     -> ...

另请注意,您实际上可能想要返回[MyData],而不是MyData

对于它的价值,编写此函数的更好方法可能是

myFunction :: [MyData] -> [MyData]
myFunction xs = [ x | x@(Age _) <- xs ]

或者您可以使用更高阶函数而不是显式递归,这往往更容易出错:

myFunction :: [MyData] -> [MyData]
myFunction = mapMaybe (\x -> case x of Age _ -> Just x; _ -> Nothing)

编辑:请注意您在问题中使用的语言 - x的所有值都具有相同的类型,此处 - MyDataAge 10DOB 40的类型相同。它们都是相同类型的值,只是使用不同的构造函数创建的。因此,这不会过滤某个类型的值的列表 - 它会过滤某个构造函数创建的值。