[Haskell-cafe] Functional dependency failure
Bertram Felgenhauer
bertram.felgenhauer at googlemail.com
Sat Sep 6 14:56:55 UTC 2014
Alexander Pakhomov wrote:
> I have following code:
>
> import Control.Monad.Reader
> import Control.Monad.ST
> import qualified Data.Vector.Mutable as MV
> import qualified Data.Vector as V
>
> type ReadVecMonad s = ReaderT (MV.MVector s Int) (ST s)
>
> freezeV :: ReadVecMonad s (V.Vector Int)
> freezeV = ask >>= lift V.freeze
You are asking to lift a function of type
MV.MVector s Int -> ST s (V.Vector Int)
to another one of type
MV.MVector s Int -> ReaderT (MV.MVector s Int) (ST s) (V.Vector Int)
However, `lift` works on monad actions. This works:
freezeV :: ReadVecMonad s (V.Vector Int)
freezeV = ask >>= lift . V.freeze
> Trying to compile this I have "Couldn't match type ... When using functional dependencies to combine" error
> following with kind mismatch and type with literaly the same type mismatch.
Ghc's error message is wonderfully convoluted. Let's try to follow.
We know that freezeV :: ReadVecMonad s (V.Vector Int) and
(>>=) :: Monad m => m a -> (a -> m b) -> m b, so that
ask :: ReadVecMonad s r
lift V.freeze :: r -> ReadVecMonad s (V.Vector Int)
ghc infers the following type for `lift V.freeze`:
lift V.freeze
:: (Control.Monad.Primitive.PrimMonad m, MonadTrans t) =>
t ((->) (V.MVector (Control.Monad.Primitive.PrimState m) a))
(m (V.Vector a))
To unify the two types for `lift V.freeze`, we let
t = (->)
r = (->) (V.MVector (Control.Monad.Primitive.PrimState m) a)
m = ReadVecMonad s
a = Int
Therefore, we must have
ask :: ReadVecMonad s
((->) (V.MVector (Control.Monad.Primitive.PrimState (ReadVecMonad s)) Int))
ask :: ReaderT (MV.MVector s Int) (ST s)
((->) (V.MVector (Control.Monad.Primitive.PrimState (ReadVecMonad s)) Int))
We also know that ask :: MonadReader m r => m r. In our case,
m = ReaderT (MV.MVector s Int) (ST s). From the instance
MonadReader r (ReaderT r m) and the functional dependency m -> r, we
conclude that
r = MV.MVector s Int.
This, of course, is in contradiction with the already established
r = (->) (V.MVector (Control.Monad.Primitive.PrimState (ReadVecMonad s)) Int)
Phew.
The kind errors later on arise from the fact that we have replaced
t :: (* -> *) -> * -> * (t is supposed to be a monad transformer)
by (->) :: * -> * -> *, and r :: * by something of kind * -> *.
Newer ghc versions seem to arrive at r = MV.MVector s Int before
r = (->) (V.MVector (Control.Monad.Primitive.PrimState (ReadVecMonad s)) Int)
and do not mention functional dependencies as a result.
Hope that helps,
Bertram
> There's full error message:
>
> STRead.hs:9:11:
> Couldn't match type `V.MVector s Int'
> with `(->)
> (V.MVector
> (Control.Monad.Primitive.PrimState
> (ReaderT (V.MVector s Int) (ST s)))
> Int)'
> When using functional dependencies to combine
> MonadReader r (ReaderT r m),
> arising from the dependency `m -> r'
> in the instance declaration in `Control.Monad.Reader.Class'
> MonadReader
> ((->)
> (V.MVector
> (Control.Monad.Primitive.PrimState
> (ReaderT (V.MVector s Int) (ST s)))
> Int))
> (ReaderT (V.MVector s Int) (ST s)),
> arising from a use of `ask' at STRead.hs:9:11-13
> In the first argument of `(>>=)', namely `ask'
> In the expression: ask >>= lift V.freeze
>
>
> STRead.hs:9:19:
> Couldn't match kind `* -> *' with `*'
> Expected type: (->)
> (V.MVector
> (Control.Monad.Primitive.PrimState
> (ReaderT (V.MVector s Int) (ST s)))
> Int)
> -> ReaderT (V.MVector s Int) (ST s) (V.Vector Int)
> Actual type: (->)
> (V.MVector
> (Control.Monad.Primitive.PrimState
> (ReaderT (V.MVector s Int) (ST s)))
> Int)
> -> ReaderT (V.MVector s Int) (ST s) (V.Vector Int)
> Kind incompatibility when matching types:
> (->)
> (V.MVector
> (Control.Monad.Primitive.PrimState
> (ReaderT (V.MVector s Int) (ST s)))
> Int) :: * -> *
> (->)
> (V.MVector
> (Control.Monad.Primitive.PrimState
> (ReaderT (V.MVector s Int) (ST s)))
> Int) :: *
> In the return type of a call of `lift'
> In the second argument of `(>>=)', namely `lift V.freeze'
>
> STRead.hs:9:24:
> Couldn't match kind `*' with `* -> *'
> Expected type: V.MVector
> (Control.Monad.Primitive.PrimState
> (ReaderT (V.MVector s Int) (ST s)))
> Int
> -> ReaderT (V.MVector s Int) (ST s) (V.Vector Int)
> Actual type: V.MVector
> (Control.Monad.Primitive.PrimState
> (ReaderT (V.MVector s Int) (ST s)))
> Int
> -> ReaderT (V.MVector s Int) (ST s) (V.Vector Int)
> Kind incompatibility when matching types:
> (->)
> (V.MVector
> (Control.Monad.Primitive.PrimState
> (ReaderT (V.MVector s Int) (ST s)))
> Int) :: *
> (->)
> (V.MVector
> (Control.Monad.Primitive.PrimState
> (ReaderT (V.MVector s Int) (ST s)))
> Int) :: * -> *
> In the first argument of `lift', namely `V.freeze'
> In the second argument of `(>>=)', namely `lift V.freeze'
More information about the Haskell-Cafe
mailing list