The example is taken from a "Haskell programming from first principles" The goal of filter function is get rid of all the objects except those of 'DbDate' type.
On somone's github I found a way to filter sum types with list comprehension and pattern matching(1). Now I am trying to find a way to redefine this filter with a lambda function(2) or normal "case of" of "if then" function. I do not know how to properly check the type of arguments of a function when I deal with custom data type.
Book doesn't introduce the reader to any super specific library functions, just standard maps, folds, filters and other stuff you'd find in prelude.
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
You were indeed on the right track, as pattern matching is an easy way of solving this, however you will get error as your pattern-matching is not comprehensive. Also, note that if you use filter, you will still get a list of
[DatabaseItem] as filter never changes the type. You can however use
map to do it. So:
You can have a
case .. of inside your lambda function:
filterDbDate' :: [DatabaseItem] -> [UTCTime] filterDbDate' = map (/(DbDate x) -> x) .filter (/x -> case x of DbDate x -> True _ -> False)
Recursion + Pattern Matching
However I think it's more clear using a recursion:
filterDbDate'' :: [DatabaseItem] -> [UTCTime] filterDbDate''  =  filterDbDate'' ((DbDate d):ds) = d : filterDbDate ds filterDbDate'' (_:ds) = filterDbDate ds
To be honest, when you have to mix up filter and map, and your lambdas are easy like this one, list comprehensions like yours are the cleanest way:
filterDbDate ds = [d | (DbDate d) <- ds]