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

Bab*_*ham 0 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
Run Code Online (Sandbox Code Playgroud)

错误:

"Age is applied to too few arguments"
Run Code Online (Sandbox Code Playgroud)

什么是最好的解决方案?

Jus*_* L. 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 _ -> ...
Run Code Online (Sandbox Code Playgroud)

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

myFunction :: [MyData] -> MyData
myFunction (x:xs) = case x of
                      Age _ -> ...
                      _     -> ...
Run Code Online (Sandbox Code Playgroud)

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

对于它的价值,一个更好的方法来编写这个函数可能是

myFunction :: [MyData] -> [MyData]
myFunction xs = [ x | x@(Age _) <- xs ]
Run Code Online (Sandbox Code Playgroud)

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

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

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