通用实例定义时触发单态限制

时间:2015-04-21 05:27:43

标签: haskell ghc

请考虑以下事项:

{-# LANGUAGE TypeFamilies, FlexibleContexts, GADTs, MultiParamTypeClasses #-}

type family F r

class (Functor t) => T t r where
  fromScalar :: r -> t r

data Foo t r where
  Foo :: t (F r) -> Foo t r
  Scalar :: r -> Foo t r

toF :: r -> F r
toF = undefined

convert :: (T t (F r))
  => Foo t r -> Foo t r
convert (Scalar c) = 
  let fromScalar' = fromScalar
  in Foo $ fromScalar' $ toF c

此代码与GHC 7.8.4编译。

当我为T添加通用实例时(需要FlexibleInstances):

instance (Functor t, Num r) => T t r

GHC抱怨:

Could not deduce (Num (F r)) arising from a use of ‘fromScalar’
    from the context (T t (F r))
      bound by the type signature for
                 convert :: (T t (F r)) => Foo t r -> Foo t r
      at Main.hs:(17,12)-(18,23)
    In the expression: fromScalar
    In an equation for ‘fromScalar'’: fromScalar' = fromScalar
    In the expression:
      let fromScalar' = fromScalar in Foo $ fromScalar' $ toF c

我记得this question,但似乎存在一些关键差异。首先也是最重要的一点,GHC并没有抱怨前期。其次,我没有RankNTypes,这似乎是问题的核心问题。最后,添加NoMonoLocalBinds并没有帮助。奇怪的是,添加NoMonomorphismRestriction 将错误消息从抱怨fromScalar更改为有关fromScalar'的相同消息。

当然,可以通过向fromScalar添加类型签名并添加ScopedTypeVariables来修复此问题:

convert :: forall t r . (T t (F r))
  => Foo t r -> Foo t r
convert (Scalar c) = 
  let fromScalar' = fromScalar :: F r -> t (F r)
  in Foo $ fromScalar' $ toF c
虽然取消这些限制并没有帮助,但是我愿意承认一些单形类型的东西在这里起作用。我的问题是:为什么通过添加通用实例来触发限制?更重要的是,为什么GHC尝试匹配通用实例而不是使用T (F r)约束?这似乎是错误的,并且有this bug的气味。

1 个答案:

答案 0 :(得分:0)

这是GHC错误#10338。不幸的是,它似乎不会很快得到解决。