2015-12-15 7 views
7

Ich habe dies nur auf Haskell-Cafe gefragt, aber ich denke, ich könnte auch hier fragen. Ist die folgende Monad Instanz für Backwards m gültig?Gibt Backwards eine Monad-Instanz zu?

{-# Language RecursiveDo #-} 

import Control.Applicative.Backwards 
import Control.Monad.Fix 

instance MonadFix m => Monad (Backwards m) where 
    m >>= f = Backwards $ 
    do 
     fin <- forwards (f int) 
     int <- forwards m 
     pure fin 

Wenn ja, könnte ich das auch hinzufügen?

instance MonadFix m => MonadFix (Backwards m) where 
    mfix f = Backwards $ mfix (forwards . f) 

Antwort

2

Für diese f müssten faul sein, das heißt, muss der Effekt nicht auf das Argument ab. Die docs sagen

mfix f die Aktion ausführt f nur einmal, mit dem letztendlichen Ausgang wieder als Eingang zugeführt. Daher sollte f nicht streng sein, denn dann würde mfix f divergieren.

Buf wenn f in Ihrem Fall m >>= f streng sein wird, dann wird so sein, der Block mfix weitergegeben.

Betrachten wir ein praktisches Beispiel, wo mreadLine >>= putStrLn ist. Das Umkehren der Reihenfolge würde bedeuten "die Daten drucken und dann lesen". Sofern die Wirkung der Funktion hinter >>= nicht vom Eingang abhängt, ist dies unterschiedlich.

+0

Ja, ich bin mir dieser Einschränkung bewusst, die den Nutzen der Instanz stark einschränkt. Was mir noch nicht klar ist, ist, ob diese Einschränkung ihre * Gültigkeit * beeinflusst. – dfeuer

+0

Okay, ich denke ich sehe, wie das jetzt die Dinge bricht. Ich habe eine Antwort geschrieben, von der ich vermute, dass sie sie beweist. – dfeuer

+2

Ich höre GHC 8.0 unterstützt die Zeitreise in Bezug auf 'IO'. – PyRulez

3

Nein, es ist nicht gültig; die Monadengesetze halten bestenfalls ungefähr. Wie Petr Pudlák's answer zeigt, verhält sich Backwards m >>= f nicht sehr schön, wenn f in seiner Argumentation streng ist.

Nach den Monade Gesetze,

pure() >>= (\() -> m) = m 

Aber mit diesem Beispiel, wenn ich mich nicht irre,

pure() >>= (\() -> m) = Backwards $ do 
    fin <- forwards (int `seq` m) 
    int <- pure() 
    pure fin 
    = Backwards $ fmap fst $ mfix $ \ ~(_, int) -> do 
    fin <- forwards (int `seq` m) 
    pure (fin,()) 

Wenn die zugrunde liegende Monade "streng" (dh seine >>= ist streng in seinem linken Operanden), wird dies divergieren.

Verwandte Themen