我有这些数据类型:
data Command = Back Int | Front Val deriving (Show,Eq)
data Val = Val {first::Int, second::Int, third::Int} deriving (Show, Eq)
type Program = [Command]
Run Code Online (Sandbox Code Playgroud)
我有这个功能:
foo :: Program -> Int
foo list = length (filter (==Front Val {first, second, third}) list)
Run Code Online (Sandbox Code Playgroud)
目的是仅使用FILTER来查找Front发生的次数,而foo会给出编译错误。我不确定如何表示Front的整数/ val部分。
如果(==) :: Eq a => a -> a -> Bool变量first和second没有这样的值,则不能使用相等检查。这里需要的是模式匹配。
例如,我们可以使用列表理解:
foo :: Program -> Int
foo list = length [ v | v@(Front _) <- list ]Run Code Online (Sandbox Code Playgroud)
有没有必要参数相匹配Val {},或者Val _ _ _等因为对唯一的数据构造Val类型Val。
如果您认为以后会添加更多的数据构造函数,则可以添加额外的子模式:
foo :: Program -> Int
foo list = length [ v | v@(Front (Val {})) <- list ]Run Code Online (Sandbox Code Playgroud)
或者我们可以在一个函数中进行模式匹配并使用filter :: (a -> Bool) -> [a] -> [a],例如:
foo :: Program -> Int
foo = length . filter f
where f (Front _) = True
f _ = FalseRun Code Online (Sandbox Code Playgroud)
或者如果我们包括Val数据构造函数检查:
foo :: Program -> Int
foo = length . filter f
where f (Front (Val {})) = True
f _ = FalseRun Code Online (Sandbox Code Playgroud)
就像@WillemVanOnsem在回答中所说的那样,您使用的方法不起作用。尝试使用filter (\x -> case x of { Front _ -> True; Back _ -> False }) list。您也许可以单独解决这个问题,但是如果您需要更多详细信息,请执行以下操作:
\x -> case x of { Front _ -> True; Back _ -> False }是lambda表达式。它定义了一个未命名(或匿名)函数,该函数采用一个名为named的参数x,并返回给出的值case x of { Front _ -> True; Back _ -> False }。case x of { Front _ -> True; Back _ -> False }确实模式匹配上x。如果x形式为Front _,_可以是任何地方,则返回True;否则返回False。通常,此语句的格式如下:case x of
Front _ -> True
Back _ -> False
Run Code Online (Sandbox Code Playgroud)
但是上面的紧凑语法较短,因此在这种情况下效果更好。
True当其参数为形式时返回)Front _将filter作为其参数传递。