Ich habe folgende Dolmetscher ProgramT aus dem operativen PaketDo GADTs brechen equational Argumentation in Haskell
{-# LANGUAGE GADTs #-}
import Control.Monad ((<=<))
import Control.Monad.Operational
data Motor' a where
--Define GADT
serialNewportT :: (Monad m, MonadIO m) => ProgramT Motor' m a -> m a
serialNewportT = eval <=< viewT
where
eval :: (Monad m, MonadIO m) => ProgramViewT Motor' m v -> m v
eval (Return x) = return x
eval (x :>>= k) = f x >>= serialNewportT . k
f :: (Monad m, MonadIO m) => Motor' a -> m a
f = undefined -- excluded for brevity
Der Code verwendet wird, wie es steht, zur Zeit überprüft geben Sie einfach in Ordnung. Ich möchte jedoch in der Lage sein, zu deaktivieren, wie der Interpreter verschiedene Motoren handhabt, also möchte ich f
einen Parameter machen, anstatt ihn fest codieren zu lassen. Ich habe versucht, diesen Schalter mit dem folgenden Code
{-# LANGUAGE GADTs #-}
import Control.Monad ((<=<))
import Control.Monad.Operational
data Motor' a where
--Define GADT
serialNewportT :: (Monad m, MonadIO m) => (Motor' a -> m a) -> ProgramT Motor' m a -> m a
serialNewportT f = eval <=< viewT
where
eval :: (Monad m, MonadIO m) => ProgramViewT Motor' m v -> m v
eval (Return x) = return x
eval (x :>>= k) = f x >>= serialNewportT f . k
zu machen
schlägt jedoch fehl, dieser Code mit einer Fehlermeldung
Couldn't match type ‘b’ with ‘c’
‘b’ is a rigid type variable bound by
a pattern with constructor
:>>= :: forall (instr :: * -> *) (m :: * -> *) a b.
instr b -> (b -> ProgramT instr m a) -> ProgramViewT instr m a,
in an equation for ‘eval’
‘c’ is a rigid type variable bound by
the type signature for
serialNewportT :: (Monad m, MonadIO m) =>
(Motor' c -> m c) -> ProgramT Motor' m a -> m a
Expected type: Motor' c
Actual type: Motor' b
Da ich mit einem lokalen einem von der gleichen Art des globalen Namen bin nur zu ersetzen, hätte ich gedacht, dass es ohne Probleme gearbeitet haben soll. Wie kann ich die Typen mit f
als Parameter vereinheitlichen?
Sie haben nicht richtig die Art der 'f' übersetzt. Im ursprünglichen Code könnte es mit einem Typ "Motor" a für jedes "a" instanziiert werden, aber im nicht funktionierenden Code geben Sie an, dass sein Typ genau das gleiche "a" wie in "ProgramT Motor 'ma" ist , während Sie im Funktionskörper bei einem anderen (existentiell quantifizierten) Typ 'b'' f' auf einem 'Motor' b' aufrufen. Sie brauchen wahrscheinlich nur einen höheren Rank-Typ: 'serialNewportT :: (Monad m, MonadIO m) => (forall x. Motor 'x -> mx) -> ProgramT Motor' ma -> ma' – user2407038
@ user2407038 scheint wie eine Antwort zu mir – Carsten
Ugh. Ich habe ein paar Nachforschungen über Variablen vom Typ "Bereich" angestellt, die versuchen sollten, alles in Übereinstimmung zu bringen, aber ich habe nicht auf Typen vom Rang N geschaut. Ich denke, es ist Zeit, sie endlich zu lernen. @ user2407038, wenn Sie dies eine Antwort machen möchten, werde ich Ihnen die Anerkennung dafür geben. – user640078