【发布时间】:2016-08-06 14:44:05
【问题描述】:
我正在学习Haskell Book,在第 10 章(折叠列表)中,我正在尝试解决一个关于从包含不同类型元素的列表中仅获取一种特定类型元素的练习。
作者给出以下代码:
import Data.Time
data DatabaseItem = DbString String
| DbNumber Integer
| DbDate UTCTime
deriving (Eq, Ord, Show)
theDatabase :: [DatabaseItem]
theDatabase = [ DbDate (UTCTime
(fromGregorian 1911 5 1)
(secondsToDiffTime 34123))
, DbNumber 9001
, DbString "Hello, world!"
, DbDate (UTCTime
(fromGregorian 1921 5 1)
(secondsToDiffTime 34123))
]
第一个问题是:
编写一个过滤 DbDate 值并返回一个列表的函数 其中的 UTCTime 值。
filterDbDate :: [DatabaseItem] -> [UTCTime]
filterDbDate = undefined
由于这一章都是关于折叠列表的,我假设它可以使用例如foldr 来完成。
我最初的尝试是先写一些辅助函数并在foldr中使用它们,例如:
getDbDate1 :: DatabaseItem -> UTCTime
getDbDate1 (DbDate utcTime) = utcTime
isDbDate :: DatabaseItem -> Bool
isDbDate (DbDate _) = True
isDbDate _ = False
filterDbDate1 :: [DatabaseItem] -> [UTCTime]
filterDbDate1 database = foldr ((:) . getDbDate1) [] (filter isDbDate database)
这似乎可以完成这项工作,因为:
λ> filterDbDate1 theDatabase
[1911-05-01 09:28:43 UTC,1921-05-01 09:28:43 UTC]
但我对这个解决方案并不满意,因为首先它会给出以下警告:
/Users/emre/code/haskell/chapter10_folding_lists/database.hs:36:1: Warning: …
Pattern match(es) are non-exhaustive
In an equation for ‘getDbDate1’:
Patterns not matched:
DbString _
DbNumber _
我正在使用两个辅助函数,一个用于帮助过滤掉不是 DbDate 的值,另一个用于获取 UTCTime 组件。
因此,为了摆脱非详尽的模式匹配警告并使用单个辅助函数,我决定将其编写为:
getDbDate2 :: DatabaseItem -> Maybe UTCTime
getDbDate2 (DbDate utcTime) = Just utcTime
getDbDate2 _ = Nothing
filterDbDate2 :: [DatabaseItem] -> [UTCTime]
filterDbDate2 database = foldr ((:) . getDbDate2) [] database
但是,当然,上面没有编译,因为它没有类型检查,因为,例如:
λ> foldr ((:) . getDbDate2) [] theDatabase
[Just 1911-05-01 09:28:43 UTC,Nothing,Nothing,Just 1921-05-01 09:28:43 UTC]
换句话说,它可以返回Just UTCTime 值的列表以及Nothing 值,而不仅仅是UTCTime 值的列表。
所以我的问题是:我怎样才能编写一个(帮助器?)函数,一次(这样我就不必使用filter)检查它的值是否为DbNumber,如果所以返回UTCTime 组件? (如果不是......它还必须返回一些东西(例如Nothing?),这就是我遇到麻烦的地方,即使用Maybe UTCTime,然后获取Just UTCTime值等)
【问题讨论】:
-
catMaybes :: [Maybe a] -> [a]可以在这里提供帮助。 -
函数
f = maybe [] (:[]) . getDbDate2返回一个时间的单例列表,如果有,则返回一个空列表。filterDbDate就是foldMap f。
标签: haskell