这是一个不适合我的功能,我想我需要摆脱fst。
flagHolidays :: [(C.Day,Availability)] -> Handler [(C.Day,Availability)]
flagHolidays dayPairs = do
let days = map fst dayPairs
yepNope = Prelude.map isHoliday days
availability = Prelude.map flagAvailability yepNope
return $ Prelude.zip days availability
我能想到的唯一方法是按照(x,y):(xs,ys)
的方式进行非常难看的模式匹配。删除fst
是否有意义?如果是这样,那么对这个对列表进行模式匹配的最佳方法是什么?
答案 0 :(得分:22)
在惯用的haskell代码中使用head
,tail
和init
的原因是它们不是全部函数 - 某些输入会导致错误发生。将空列表传递给任何这些函数会导致空列表异常。
fst
和snd
没有此问题,因为没有输入可以传递给那些会导致异常的函数。所以没有理由试图避免这些功能。
您的功能可以更好地编写(其他评论提供了有关此内容的详细信息),但由于使用了fst
或snd
而无法使用。
答案 1 :(得分:14)
使功能纯净,
flagHolidays = map (second $ flagAvailability . isHoliday)
要回答实际问题,除非作为参数传递fst和snd很少使用。
<编辑]嗯,我写得有点草率。这是不对的。你传递了一对配对,从不使用该对的第二个组成部分。已更正,但同样(现在使用fst
):
flagHolidays = map ((id &&& flagAvailability . isHoliday) . fst)
答案 2 :(得分:4)
dayPairs
是对的列表,因此days
应该是map fst dayPairs
。这是使用fst
惯用的一个地方,作为高阶函数的参数。除此之外,当作者忘记懒惰模式时,它主要用于推迟对的评估。
答案 3 :(得分:4)
我认为你是正确的,因为你这样做的方式似乎并不特别惯用。
除了错误之外,还有很多更好的方法。作为几个示例(可能不是最佳的,但仍然更具可读性),您可以在地图中使用lambda:
return $ map (\(d,a) -> (d, flagAvailability $ isHoliday a)) dayPairs
或者你可以使用列表理解:
return [(day, flagAvailability $ isHoliday a) | (day,a) <- dayPairs]
可能有一些聪明的方法可以使中心映射完全没有点,但即便如此也可能不值得 - 上述任何一个表达式都可以使操作相当清晰。但是,我认为消除变量dayPairs
可能是一种改进:
flagHolidays = return . map (\(d,a) -> (d, flagAvailability $ isHoliday a))