如何定义一个lambda函数,根据sum类型的子类型过滤列表?

Ada*_*s07 5 lambda haskell functional-programming custom-data-type haskell-prelude

该示例取自"基于第一原理的Haskell编程".过滤函数的目标是除去"DbDate"类型之外的所有对象.

在somone的github上,我找到了一种用列表理解和模式匹配来过滤和类型的方法(1).现在我试图找到一种方法,用lambda函数(2)或"if then"函数的正常"case"重新定义这个过滤器.当我处理自定义数据类型时,我不知道如何正确检查函数的参数类型.

本书不会向读者介绍任何超级特定的库函数,只是标准的地图,折叠,过滤器以及您在前奏中找到的其他内容.

import Data.Time

data DatabaseItem = DbString String
                  | DbNumber Integer
                  | DbDate   UTCTime
                  deriving (Eq, Ord, Show)

--List that needs to be filtered
theDatabase :: [DatabaseItem]
theDatabase =
  [ DbDate (UTCTime (fromGregorian 1911 5 1)
                    (secondsToDiffTime 34123))
  , DbNumber 9001
  , DbString "Hello, world!"
  , DbDate (UTCTime (fromGregorian 1921 5 1)
                    (secondsToDiffTime 34123))
  ]



--1 works fine, found on someone's git hub
filterDbDate :: [DatabaseItem] -> [UTCTime]
filterDbDate dbes = [x | (DbDate x) <- dbes]

--2 Looking for the eqivalents with lambda or "case" or "if then"
--pattern is not satisfactory

filterDbDate :: [DatabaseItem] -> [UTCTime]
filterDbDate dbes = filter (\(DbDate x) -> True) theDatabase
Run Code Online (Sandbox Code Playgroud)

小智 6

filter有类型,(a -> Bool) -> [a] -> [a]所以它无法更改列表的类型.

根据The Haskell 98 Report(第3.11节),你在github上发现的代码中使用的列表理解是:

filterDbDate2 :: [DatabaseItem] -> [UTCTime]
filterDbDate2 dbes = let extractTime (DbDate time) = [time]
                         extractTime _             = []
                     in concatMap extractTime theDatabase
Run Code Online (Sandbox Code Playgroud)

您可以重写extractTime使用case ... of:

filterDbDate3 :: [DatabaseItem] -> [UTCTime]
filterDbDate3 dbes = let extractTime item = case item of (DbDate time) -> [time]
                                                         _             -> []
                     in concatMap extractTime theDatabase
Run Code Online (Sandbox Code Playgroud)

并用lambda替换它:

filterDbDate4 :: [DatabaseItem] -> [UTCTime]
filterDbDate4 dbes = concatMap (\item -> 
    case item of 
        (DbDate time) -> [time]
        _             -> []) 
    theDatabase
Run Code Online (Sandbox Code Playgroud)

但是imho你使用列表理解的原始解决方案看起来最好:

filterDbDate dbes = [x | (DbDate x) <- dbes]
Run Code Online (Sandbox Code Playgroud)