对自定义数据类型使用过滤器

use*_*789 3 haskell filter

我有这些数据类型:

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部分。

Wil*_*sem 5

如果(==) :: Eq a => a -> a -> Bool变量firstsecond没有这样的值,则不能使用相等检查。这里需要的是模式匹配

例如,我们可以使用列表理解:

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 _ = False
Run Code Online (Sandbox Code Playgroud)

或者如果我们包括Val数据构造函数检查:

foo :: Program -> Int
foo = length . filter f
    where f (Front (Val {})) = True
          f _ = False
Run Code Online (Sandbox Code Playgroud)


bra*_*drn 5

就像@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)

但是上面的紧凑语法较短,因此在这种情况下效果更好。

  • 然后将上面的lambda表达式(如前所述,True当其参数为形式时返回)Front _filter作为其参数传递。