我的汽车类型有一个子类型“零件”:
data Part =
Part
{ currency :: Text
, value :: Float
}
deriving (Generic, Show)
data Car =
Car
{ brand :: Text
, engine :: Part
}
deriving (Generic, Show)
Run Code Online (Sandbox Code Playgroud)
我正在尝试访问和安装汽车列表,如下所示:
filterByEnginePrice :: [Car] -> Float -> [Car]
filterByEnginePrice cars threshold =
Prelude.filter (\car -> engine car <= threshold) cars
Run Code Online (Sandbox Code Playgroud)
但是,GHC 给了我以下错误:
• Couldn't match expected type ‘Part’ with actual type ‘Float’
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为我想过滤value
而不是过滤Part
。访问value
过滤器函数中的字段的语法是什么?
您可以使用value :: Part -> Float
getter获取该值:
filterByEnginePrice :: [Car] -> Float -> [Car]
filterByEnginePrice cars threshold = Prelude.filter (\car -> value (engine car) <= threshold) cars
Run Code Online (Sandbox Code Playgroud)
但在 lambda 表达式的头部“解包”数据构造函数更为惯用:
filterByEnginePrice :: [Car] -> Float -> [Car]
filterByEnginePrice cars threshold = Prelude.filter (\Car { engine=Part {value=v} } -> v <= threshold) cars
Run Code Online (Sandbox Code Playgroud)
或者我们可以使用@oisdk指定的无点表达式:
filterByEnginePrice :: [Car] -> Float -> [Car]
filterByEnginePrice cars threshold = Prelude.filter ((threshold >=) . value . engine) cars
Run Code Online (Sandbox Code Playgroud)