ambiguous type error when using type families, and STV is not helping

拈花ヽ惹草 提交于 2019-12-13 02:25:49

问题


{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}

class PoC m where
    type Wrapper m :: * -> *
    wrap :: l -> Wrapper m l

I'm working with haskell-src-exts, and I want to upgrade my AST to have freshly generatable labels. Since I want to do it in an extensible fashion, I created an interface like the code above. However, code to upgrade the AST doesn't work. I have the following:

upgrade :: forall f m l. (PoC m, Functor f) => f l -> f (Wrapper m l)
upgrade x = fmap (wrap :: l -> Wrapper m l) x

But with or without the use of ScopedTypeVariables, I get the same error:

/tmp/PoC.hs:10:19:
    Could not deduce (Wrapper m ~ Wrapper m0)
    from the context (PoC m, Functor f)
      bound by the type signature for
                 upgrade :: (PoC m, Functor f) => f l -> f (Wrapper m l)
      at /tmp/PoC.hs:9:12-69
    NB: `Wrapper' is a type function, and may not be injective
    The type variable `m0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Expected type: l -> Wrapper m0 l
      Actual type: l -> Wrapper m l
    In the first argument of `fmap', namely
      `(wrap :: l -> Wrapper m l)'
    In the expression: fmap (wrap :: l -> Wrapper m l) x
    In an equation for `upgrade':
        upgrade x = fmap (wrap :: l -> Wrapper m l) x

But I don't understand where GHC binds this m0. Is "may not be injective" the core of the problem here?


回答1:


Non-injectivity is the problem, indeed. Injectivity would allow GHC to know that if f a ~ f b then a ~ b but since you can have two PoC m instances with the same choice of Wrapper m type it's hard to know what m was after you've solved for what Wrapper m is.

You should be able to fix it by adding an input term to wrap which contains the m type parameter. This can be a proxy argument which is never evaluated

data Proxy a = Proxy

class PoC m where
  type Wrapper m :: * -> *
  wrap :: proxy m -> l -> Wrapper m l

instance PoC () where
  type Wrapper () = Maybe
  wrap _ = return

aUnit :: Proxy ()
aUnit = Proxy

upgrade :: (PoC m, Functor f) => proxy m -> f l -> f (Wrapper m l)
upgrade aProxy x = fmap (wrap aProxy) x


来源:https://stackoverflow.com/questions/19838679/ambiguous-type-error-when-using-type-families-and-stv-is-not-helping

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!