2016-04-20 12 views
1

Manche Dinge scheint unglaublich zu sein:Warum ist es möglich, diese Typen zu ersetzen?

foo :: a -> StateT Env (ReaderT Env (ErrorT String IO)) String

mit
foo :: a -> ErrorT String IO String

ersetzt werden Wie ist es möglich? Immerhin sind sie absolut verschiedene Typen ...

+1

In der Regel ist es wegen Polymorphismus und Überladung. Es ist nicht möglich, genau zu sagen, ohne den Code für 'foo' zu sehen. – Lee

Antwort

7

Es ist natürlich nicht möglich, diese in allen Umständen durch diese zu ersetzen. Wenn Sie beispielsweise explizit ErrorT . return $ Left "Muahar" verwenden, muss eine ErrorT String m a sein.

Jedoch sind beide Arten von Form a -> M String mit einer (transformator stack) monadisch M das eine Instanz von MonadIO und MonadError String ist. Wenn diese Funktion also nur mit Aktionen des Forms liftIO ioaction und möglicherweise throwError und catchError definiert wird, funktioniert sie wie jede dieser Monaden. Der allgemeine Typ ist

foo :: (MonadIO m, MonadError String m) => a -> m String 
+2

Wenn Sie Ihre eigene Typ-Signatur aus 'foo' entfernen und dann': t foo' in ghci verwenden, können Sie den allgemeinsten Typ sehen, den 'foo' haben kann, was oft sehr hilfreich ist. Auch ': i SomeFunctionOrTypeOrTypeClass' kann sehr nützlich sein, wenn man Monad-Stacks herausfinden möchte. –

+1

Richtig, obwohl dies nicht als Aufforderung verstanden werden sollte, Typ-Signaturen in Code, der eigentlich _used_ sein soll, wegzulassen. – leftaroundabout

+0

Manchmal ist auch der abgeleitete Typ, der von ghci angezeigt wird, nicht wirklich der nützlichste - oder möchten Sie Dokumentation, die besagt 'smoothInterpolate :: (Data.LinearMap.HerMetric.HasMetric 'y, Data.LinearMap.HerMetric.HasMetric' (Data.LinearMap.HerMetric.DualSpace y, '... (mehr Einschränkungen) ...' Data.LinearMap.HerMetric.DualSpace (Data.LinearMap.HerMetric.DualSpace y) ~ y, Skalar (Needly y) ~ manifolds-0.2.1.0: Data.Manifold.Types.Primitive.ℝ) => Data.List.NonEmpty.NonEmpty (x, y) -> x -> y'? – leftaroundabout