Mic*_*ard 17 monads haskell function-composition
我决定今天是我修复一些不必要地在monadic动作中运行的纯函数的那一天.这就是我所拥有的.
flagWorkDays :: [C.Day] -> Handler [WorkDay]
flagWorkDays dayList =
flagWeekEnds dayList >>=
flagHolidays >>=
flagScheduled >>=
flagASAP >>=
toWorkDays
Run Code Online (Sandbox Code Playgroud)
这是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
Run Code Online (Sandbox Code Playgroud)
flagHolidays
遵循类似的模式.toWorkDays
只是将一种类型更改为另一种类型,并且是纯函数.
flagScheduled
,flagASAP
是monadic行动.我不确定如何将monadic动作与惯用语中的纯函数结合起来flagWorkDays
.有人可以帮我解决flagWorkDays
,假设flagWeekEnds
并且flagHolidays
已经变得纯净了吗?
ham*_*mar 29
让我们退一步吧.你有两种类型的函数,一些是纯粹的表单类型a -> b
,一些是monadic类型a -> m b
.
为了避免混淆,让我们也坚持从右到左的构图.如果你喜欢阅读左到右,只是反转的功能的顺序和替换(<=<)
用(>=>)
,并(.)
用(>>>)
从Control.Arrow
.
然后有四种可能性来组成这些.
纯净然后纯净.使用常规功能组合(.)
.
g :: a -> b
f :: b -> c
f . g :: a -> c
Run Code Online (Sandbox Code Playgroud)纯粹的monadic.也用(.)
.
g :: a -> b
f :: b -> m c
f . g :: a -> m c
Run Code Online (Sandbox Code Playgroud)Monadic然后monadic.使用kleisli成分(<=<)
.
g :: a -> m b
f :: b -> m c
f <=< g :: a -> m c
Run Code Online (Sandbox Code Playgroud)Monadic然后纯洁.使用fmap
的纯函数和 (.)
作曲.
g :: a -> m b
f :: b -> c
fmap f . g :: a -> m c
Run Code Online (Sandbox Code Playgroud)忽略所涉及类型的细节,您的功能是:
flagWeekEnds :: a -> b
flagHolidays :: b -> c
flagScheduled :: c -> m d
flagASAP :: d -> m e
toWorkDays :: e -> f
Run Code Online (Sandbox Code Playgroud)
让我们从顶部开始.flagWeekEnds
并且flagHolidays
都是纯粹的.情况1.
flagHolidays . flagWeekEnds
:: a -> c
Run Code Online (Sandbox Code Playgroud)
这很纯粹.接下来是flagScheduled
,这是monadic.案例2.
flagScheduled . flagHolidays . flagWeekEnds
:: a -> m d
Run Code Online (Sandbox Code Playgroud)
接下来flagASAP
,现在我们有两个monadic函数.案例3.
flagASAP <=< flagScheduled . flagHolidays . flagWeekEnds
:: a -> m e
Run Code Online (Sandbox Code Playgroud)
最后,我们有纯粹的功能toWorkDays
.案例4.
fmap toWorkDays . flagASAP <=< flagScheduled . flagHolidays . flagWeekEnds
:: a -> m f
Run Code Online (Sandbox Code Playgroud)
我们已经完成了.
这不是很困难.你基本上只需更换(>>=)
由(.)
和翻转操作数的顺序.do
语法可能有助于澄清.我还使用Kleisli组合器(鱼)制作了示例pointfree (<=<) :: (b -> m c) -> (a -> m b) -> a -> m c
,主要(.)
用于monad.
import Control.Monad
flagWorkDays :: [C.Day] -> Handler [WorkDay]
flagWorkDays =
fmap toWorkDays . flagASAP <=< flagScheduled . flagHolidays . flagWeekEnds
Run Code Online (Sandbox Code Playgroud)
要填写FUZxxl的答案,让我们简化flagWeekEnds
:
flagWeekEnds :: [C.Day] -> [(C.Day,Availability)]
flagWeekEnds days = days `zip` map (flagAvailability . isWorkDay) days
Run Code Online (Sandbox Code Playgroud)
你经常在变量名(day
- > days
)之后加一个"s" 作为一个列表(就像你用英语复数一样).