Распространенной ошибкой является использование do
в функциях, которые не имеют монадического контекста.Это одна из причин, почему запись do
считается вредной [Haskell-wiki] .do
выражения на самом деле синтаксический сахар .В отчете Haskell описывается, как " desugar " сделать это.
Для таких функций, как listToItem :: [String] -> Item
, вы не должны использовать нотацию do
.Это не будет работать, тем более что Item
не является типом Monad
.
Мы можем, например, реализовать listToItem
как:
listToItem :: [String] -> Item
listToItem [] = error "Empty List"
listToItem [n, e, s, p] = <b>Item (read n) (parseDate e) (read s) (read p)</b>
listToItem _ = error "To few/much Arguments"
Чтобы вычислить daysAway
, возможно, было бы лучше сделать это чистой функцией и вычислить разницу с помощью параметра Day
:
daysAway :: Day -> Day -> Integer
daysAway = flip diffDays
Затем analyseItems
можно просто filter :: (a -> Bool) -> [a] -> [a]
элементы в daysAway
:
analyseItems :: Day -> [Item] -> [Item]
analyseItems today = filter (<b>(0 >) . daysAway today . expire</b>)
Здесь мы, таким образом, можем получить список Item
s, срок действия которых истек вданное Day
.Нам здесь вообще не нужна функция getExpired
, или мы используем рекурсию для фильтрации.
Мы можем transform
список строк до Item
с map :: (a -> b) -> [a] -> [b]
:
transform :: [[String]] -> [Item]
transform = <b>map</b> listToItem
Теперь мы можем сделать IO Item
для получения просроченных элементов, таких как:
getExpired :: [Item] -> IO [Item]
getExpired items = fmap (flip analyseItems items) today
Я оставляю парсинг файла CSV, обрабатывая его черезtransform
, а затем отфильтруйте его с помощью getExpired
в качестве упражнения.