So vor kurzem ich mit dieser netten Idee kam, in der Hoffnung, des Teilen Code zwischen dem strengen und faul State
Transformator Module:Abdeckung aller Fälle eines geförderten Datentypen
{-# LANGUAGE FlexibleInstances, DataKinds, KindSignatures #-}
module State where
data Strictness = Strict | Lazy
newtype State (t :: Strictness) s a = State (s -> (s, a))
returnState :: a -> State t s a
returnState x = State $ \s -> (s, x)
instance Monad (State Lazy s) where
return = returnState
State ma >>= amb = State $ \s -> case ma s of
~(s', x) -> runState (amb x) s'
instance Monad (State Strict s) where
return = returnState
State ma >>= amb = State $ \s -> case ma s of
(s', x) -> runState (amb x) s'
get :: State t s s
get = State $ \s -> (s, s)
put :: s -> State t s()
put s = State $ \_ -> (s,())
Sie können sehen, dass get
und put
Beide funktionieren ohne Duplizierung - keine Klasseninstanzen, nichts - sowohl bei den strikten als auch den faulen Typen. Ich
pro :: (Monad (State t [Bool])) => State t [Bool]()
-- otherwise as before
Dann: Doch obwohl ich beide möglichen Fälle für Strictness
decken, ich habe keine Monade Instanz für State t s a
im Allgemeinen:
-- from http://blog.melding-monads.com/2009/12/30/fun-with-the-lazy-state-monad/
pro :: State t [Bool]()
pro = do
pro
s <- get
put (True : s)
-- No instance for (Monad (State t [Bool])) arising from a do statement
Folgende funktioniert gut, wenn auch erfordern FlexibleContexts
kann t
bei Lazy
oder instanziieren und das Ergebnis ausführen und bekommen, was ich erwarte. Aber warum muss ich diesen Kontext geben? Ist das eine konzeptionelle oder praktische Einschränkung? Gibt es einen Grund, warum ich vermisse, warum Monad (State t s a)
eigentlich nicht hält, oder gibt es einfach keine Möglichkeit, GHC davon zu überzeugen?
(abgesehen: den Kontext Monad (State t s)
mit nicht Arbeit.
Could not deduce (Monad (State t [Bool])) arising from a do statement
from the context (Monad (State t s))
, die nur noch mehr verwirrt mich Sicherlich ist der ehemalige ableitbar von letzterem?)
Es ist in der Tat eine Einschränkung von 'DataKinds'. Ich habe gesehen, dass etwas Ähnliches passiert ist, wo GHC nicht herausgefunden hat, dass die Muster einer GADT mit "DataKinds" erschöpfend waren, und es erzeugte Vorschläge, die keine Typ-Überprüfung durchführen würden. –