我决定今天是我修复一些不必要地在monadic动作中运行的纯函数的那一天 . 这就是我所拥有的 .
flagWorkDays :: [C.Day] -> Handler [WorkDay]
flagWorkDays dayList =
flagWeekEnds dayList >>=
flagHolidays >>=
flagScheduled >>=
flagASAP >>=
toWorkDays
这是flagWeekEnds,截至目前 .
flagWeekEnds :: [C.Day] -> Handler [(C.Day,Availability)]
flagWeekEnds dayList = do
let yepNope = Prelude.map isWorkDay dayList
availability = Prelude.map flagAvailability yepNope
return $ Prelude.zip dayList availability
flagHolidays
遵循类似的模式 . toWorkDays
只是将一种类型更改为另一种类型,并且是纯函数 .
flagScheduled
和 flagASAP
是monadic动作 . 我不确定如何在 flagWorkDays
中以惯用方式将monadic动作与纯函数结合起来 . 有人可以帮我修复 flagWorkDays
,假设 flagWeekEnds
和 flagHolidays
已经变得纯净吗?
3 回答
让我们退一步吧 . 您有两种类型的函数,一些是纯函数,类型为
a -> b
,另一些是a -> m b
类型的monadic .为了避免混淆,让我们也坚持从右到左的构图 . 如果您希望从左向右阅读,只需反转函数的顺序,并将
(<=<)
替换为(>=>)
,将(.)
替换为(>>>)
来自Control.Arrow
.然后有四种可能性来组成这些 .
(.)
.(.)
.(<=<)
.fmap
并使用(.)
撰写 .忽略所涉及类型的细节,您的功能是:
让我们从顶部开始 .
flagWeekEnds
和flagHolidays
都是纯粹的 . 情况1 .这很纯粹 . 接下来是
flagScheduled
,这是monadic . 案例2 .接下来是
flagASAP
,现在我们有两个monadic函数 . 案例3 .最后,我们有纯函数
toWorkDays
. 案例4 .我们已经完成了 .
要填写FUZxxl 's answer, let' s pureify
flagWeekEnds
:你经常在变量名(
day
- >days
)之后放一个"s"列表(就像你用英语复数一样) .这不是很困难 . 你基本上只需要
(.)
替换(>>=)
并翻转操作数顺序 .do
语法可能有助于澄清 . 我还使用Kleisli组合器(鱼)(<=<) :: (b -> m c) -> (a -> m b) -> a -> m c
制作了示例pointfree,对于monad来说基本上是(.)
.