Frage

Ich möchte mein eigenes Monade erstellen. Das ist, was ich schrieb:

data LeafConType a = LeafCon (a,Int,Int)

instance Monad (LeafConType ) where
return = LeafCon 
lc@(LeafCon (t,i,n)) >>= f = if i>=n
                                then lc
                                else f (t,i,n)

Aber das tun sie nicht arbeiten. GHC sagt:

leafcon.hs:26:1:
    Occurs check: cannot construct the infinite type: a = (a, Int, Int)
    When generalising the type(s) for `return'
    In the instance declaration for `Monad LeafConType'

leafcon.hs:27:1:
    Occurs check: cannot construct the infinite type: a = (a, Int, Int)
    When generalising the type(s) for `>>='
    In the instance declaration for `Monad LeafConType'

Was ist daran falsch?


Ich möchte Berechnungen tun, während ich niedriger als n ist. n sollte ich sein Konstanten wissen noch nicht, wie man diese richtig zu tun. Es sollte eine gewisse Mischung aus Staat und vielleicht sein. Wenn Sie einige Ratschläge haben, fühlen sich frei, es mit mir zu teilen: P

War es hilfreich?

Lösung

Über return:

Prelude> :t return
return :: (Monad m) => a -> m a 

So return nimmt ein Argument vom Typ a und kehrt etwas vom Typ m a. In diesem Fall m ist LeafConType, so LeafConType a zurückgeführt wird.

Nehmen wir nun an, dass wir True passieren. Dann a = Bool, so muss der Rückgabetyp LeafConType Bool sein. Allerdings definieren Sie:

return = LeafCon

So wird return True LeafCon True. Aber das ist nicht erlaubt, weil die Typdefinition von LeafConType besagt, dass

data LeafConType a = LeafCon (a, Int, Int)

Also für LeafConType Bool das Argument LeafCon muss Typ (Bool, Int, Int) haben, nicht nur Bool. Und das ist, was die Compiler-Fehler bedeutet: a nicht die gleiche wie (a, Int, Int) sein kann. Sie Zustand:

  

Ich möchte Berechnungen tun, während i niedriger als n ist.

Das bedeutet, dass Sie einige Standardwerte für i und n benötigen, denn sonst wird es unmöglich sein return zu definieren. Wenn beide auf Null gesetzt sind, dann könnte man definieren:

return a = LeafCon (a, 0, 0)

Über (>>=):

Prelude> :t (>>=)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b

Überprüfen Sie nun Ihre Implementierung (etwas andere Schreibweise, gleiche Idee):

lc@(LeafCon (t, i, n)) >>= f | i >= n    = lc 
                             | otherwise = f t

Was wir hier sehen ist, dass lc zurückgegeben wird, wenn i >= n. Aber lc ist vom Typ LeafConType a, während f eine Funktion ist, die einen Wert vom Typ LeafConType b zurückgeben kann, für jeder b. Als Ergebnis könnte es sein, dass b zu a nicht gleich ist und daher diese Arten nicht übereinstimmen. Abschließend müssen Sie ernsthaft selbst eine Frage stellen:

Kann diese Art der Berechnung als Monade ohnehin ausgedrückt werden?

Andere Tipps

Die Funktionen, die Sie für >>= und return angegeben nicht die Typen erfüllen erforderlich durch Monad:

return :: a -> LeafConType a

In Anbetracht der Erklärung

return = LeafCon

Sie geben die Funktion, die nicht kompatiblen Typ

return :: (a, Int, Int) -> LeafConType a

Eine Aussage wie return 42 wäre daher in der Monade unmöglich sein.

Ich verstehe nicht, was Ihr Monade überhaupt tun sollte. Zuerst nehmen Sie einen Blick auf einfache, Arbeits Monaden!

instance Monad [] where
    (>>=) = concatMap
    return a = [a]

instance Monad Maybe where
    return = Just
    (Just x) >>= f = f x
    Nothing >>= f = Nothing

Geht man von Ihrer Beschreibung dessen, was Sie möchten, dass Ihre Monade zu tun, ich glaube, Sie etwas ein bisschen wie diese wollen:

data LeafConType a = LeafCon { runLeafCon' :: Int -> Int -> (Maybe a, Int, Int) }

runLeafCon :: Int -> Int -> LeafConType a -> Maybe a
runLeafCon i n lc = let (t, _, _) = runLeafCon' lc i n in t

getI :: LeafConType Int
getI = LeafCon $ \i n -> (Just i, i, n)

getN :: LeafConType Int
getN = LeafCon $ \i n -> (Just n, i, n)

setI :: Int -> LeafConType ()
setI i = LeafCon $ \_ n -> (Just (), i, n)

setN :: Int -> LeafConType ()
setN n = LeafCon $ \i _ -> (Just (), i, n)

instance Monad LeafConType where
    return t = LeafCon $ \i n -> if (i < n) 
                                 then (Just t, i, n) 
                                 else (Nothing, i, n)

    (LeafCon k) >>= f = 
        LeafCon $ \i n -> 
            let (t, i', n') = k i n
            in case t of
                 Nothing -> (Nothing, i', n')
                 (Just t') -> if (i' < n')
                              then runLeafCon' (f t') i' n'
                              else (Nothing, i, n)


example :: Int -> LeafConType ((), Int)
example x = do 
  i <- getI
  m <- setI (i + x)
  return (m, i + x)

Einige Beispiele:

*Main> runLeafCon 2 10 $ example 4
Just ((),6)
*Main> runLeafCon 2 10 $ example 8
Nothing
*Main> runLeafCon 2 10 $ example 7
Just ((),9)

Ich warf diese zusammen ziemlich schnell, es ist ziemlich hässlich, und ich habe nicht überprüft, um zu sehen, ob es eine der Monad Gesetze gehorcht, so Nutzung auf eigene Gefahr! :)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top