haskell - qué - funciones puras js
¿Cómo organizo idiomáticamente mis funciones puras con mis acciones monádicas? (3)
Decidí que hoy es el día en que arregle algunas de mis funciones puras que se ejecutan innecesariamente en una acción monádica. Esto es lo que tengo.
flagWorkDays :: [C.Day] -> Handler [WorkDay]
flagWorkDays dayList =
flagWeekEnds dayList >>=
flagHolidays >>=
flagScheduled >>=
flagASAP >>=
toWorkDays
Aquí está flagWeekEnds, a partir de ahora.
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
sigue un patrón similar. toWorkDays
simplemente cambia un tipo a otro, y es una función pura.
flagScheduled
, y flagASAP
son acciones monádicas. No estoy seguro de cómo combinar las acciones monádicas con las funciones puras de forma idiomática en flagWorkDays
. ¿Podría alguien ayudarme a arreglar los flagWorkDays
, asumiendo que los flagWeekEnds
flagHolidays
flagWeekEnds
y los de vacaciones de flagHolidays
se han purificado?
No es muy dificil Básicamente, solo reemplaza (>>=)
por (.)
Y cambia el orden de los operandos. do
sintaxis puede ayudar a aclarar. También hice el ejemplo sin punto usando el combinador Kleisli (fish) (<=<) :: (b -> mc) -> (a -> mb) -> a -> mc
, que es esencialmente (.)
Para mónadas.
import Control.Monad
flagWorkDays :: [C.Day] -> Handler [WorkDay]
flagWorkDays =
fmap toWorkDays . flagASAP <=< flagScheduled . flagHolidays . flagWeekEnds
Para completar la respuesta de FUZxxl, purifiquemos flagWeekEnds
:
flagWeekEnds :: [C.Day] -> [(C.Day,Availability)]
flagWeekEnds days = days `zip` map (flagAvailability . isWorkDay) days
A menudo se coloca una "s" después de los nombres de las variables ( day
-> days
) cuando es una lista (como lo hace con el plural en inglés).
Vamos a dar un paso atrás por un momento. Tiene dos tipos de funciones, algunas puras con tipos de la forma a -> b
, y algunas monádicas de tipo a -> mb
.
Para evitar confusiones, sigamos con la composición de derecha a izquierda. Si prefiere leer de izquierda a derecha, simplemente invierta el orden de las funciones y reemplace (<=<)
con (>=>)
, y (.)
Con (>>>)
de Control.Arrow
.
Hay entonces cuatro posibilidades de cómo se pueden componer.
Puro entonces puro. Usar la función de composición regular
(.)
.g :: a -> b f :: b -> c f . g :: a -> c
Pura entonces monádica . También use
(.)
.g :: a -> b f :: b -> m c f . g :: a -> m c
Monádico entonces monádico . Utilice la composición kleisli
(<=<)
.g :: a -> m b f :: b -> m c f <=< g :: a -> m c
Monádico entonces puro . Usa
fmap
en la función pura y(.)
Para componer.g :: a -> m b f :: b -> c fmap f . g :: a -> m c
Ignorando los aspectos específicos de los tipos involucrados, sus funciones son:
flagWeekEnds :: a -> b
flagHolidays :: b -> c
flagScheduled :: c -> m d
flagASAP :: d -> m e
toWorkDays :: e -> f
Vayamos desde la cima. flagWeekEnds
y flagHolidays
son puros. Caso 1.
flagHolidays . flagWeekEnds
:: a -> c
Esto es puro El siguiente es flagScheduled
, que es monádico. Caso 2.
flagScheduled . flagHolidays . flagWeekEnds
:: a -> m d
El siguiente es flagASAP
, ahora tenemos dos funciones monádicas. Caso 3.
flagASAP <=< flagScheduled . flagHolidays . flagWeekEnds
:: a -> m e
Y finalmente, tenemos la función pura de trabajar en toWorkDays
. Caso 4.
fmap toWorkDays . flagASAP <=< flagScheduled . flagHolidays . flagWeekEnds
:: a -> m f
Y hemos terminado.