Większość monadycznych funkcji przyjmuje czyste argumenty i zwraca monadyczną wartość. Ale istnieje kilka, które również potrzebują monadycznego argumenty, na przykład:Jak kodować akcje, które przyjmują monadyczne argumenty za pomocą darmowych (lub swobodnych) monad?
mplus :: (MonadPlus m) => m a -> m a -> m a
finally :: IO a -> IO b -> IO a
forkIO :: m() -> m ThreadId
-- | From Control.Monad.Parallel
forkExec :: m a -> m (m a)
Każdy z nich wydaje się, aby przywołać inny problem i nie mogę uzyskać zrozumienie ogólny sposób jak kodują takie działania za pomocą darmowe monady.
Zarówno
finally
iforkIO
Problemem jest to, że monadycznego argument jest innego typu niż wynik. Ale dla za darmo jeden musiałby być tego samego typu, ponieważIO a
zostaje zastąpiony przez zmienną typu typu kodowania, taką jakdata MyFunctor x = Finally x x x
, która kodowałaby tylkoIO a -> IO a -> IO a
.W From zero to cooperative threads in 33 lines of Haskell code autor używa
Fork next next
pięść do wdrożeniacFork :: (Monad m) => Thread m Bool cFork = liftF (Fork False True)
a następnie wykorzystuje je do wdrożenia
fork :: (Monad m) => Thread m a -> Thread m()
gdzie wejście i wyjście mają różne rodzaje. Ale nie rozumiem, czy zostało to uzyskane przy użyciu jakiegoś procesu lub po prostu pomysłu ad-hoc, który działa w tym konkretnym celu.
mplus
to szczególnie kłopotliwe: naiwne kodowanie jakodata F b = MZero | MPlus b b
rozdziela się
>>=
i suggested better implementation jest bardziej skomplikowane. A także natywną implementację darmowegoMonadPlus
was removed from free.W freer to realizowane poprzez dodanie
data NonDetEff a where MZero :: NonDetEff a MPlus :: NonDetEff Bool
Dlaczego
MPlus
NonDetEff Bool
zamiastNonDetEff a a
? I czy istnieje sposób, aby zadziałało to zFree
, gdzie potrzebujemy typ danych, aby być funktorem, innym niż używanie CoYoneda functor?- Dla
forkExec
Nie mam pojęcia, jak w ogóle postępować.
Wydaje mi się, że implementacja zależy nie od typu funkcji, ale od jej semantyki. "Ale nie rozumiem, czy zostało to uzyskane przy użyciu jakiegoś procesu" Myślę, że "proces" tutaj po prostu modeluje prawidłowo domenę. Na przykład, myślę, że kodowanie 'finally' będzie bardziej oczywiste, jeśli najpierw spróbujesz kodować" najbardziej ogólne "funkcje wyjątku (' throw', 'catch'?). Typ 'finally' jest taki sam jak' <* '.. więc teoretycznie nie ma powodu, aby funkcja tego typu nie mogła być zakodowana (może po prostu nie bezpośrednio ..). – user2407038
@ user2407038 Rozumiem, co masz na myśli. Ale interesuje mnie podejście "mechanicznie kodują cały interfejs i niech tłumacz będzie martwić się szczegółami implementacji". –