我试图迭代自定义数据类型列表,并确定特定类型的值。在这种情况下,我希望列表中的年龄:
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"
对此最好的解决方案是什么?
答案 0 :(得分:5)
你真的没有x == Age
......这没有意义。您只能将x
与MyData
类型的其他值进行比较,例如Age 10
,DOB 40
或Name "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
的所有值都具有相同的类型,此处 - MyData
。 Age 10
与DOB 40
的类型相同。它们都是相同类型的值,只是使用不同的构造函数创建的。因此,这不会过滤某个类型的值的列表 - 它会过滤某个构造函数创建的值。