按嵌套字段过滤

tim*_*lim 3 haskell

我的汽车类型有一个子类型“零件”:

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过滤器函数中的字段的语法是什么?

Wil*_*sem 5

您可以使用value :: Part -> Floatgetter获取该值:

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)