在GHCi中键入Family Shenanigans

时间:2014-12-15 18:10:33

标签: haskell ghc

这是我的代码:

{-# LANGUAGE TypeFamilies, TypeOperators, DataKinds, PolyKinds, FlexibleContexts, UndecidableInstances #-}

module Foo where

import Data.Singletons.Prelude
import Data.Type.Equality

data TP a b

-- foldl (\(bool, r) x -> (bool && (r == x), r)) (True, head xs) xs
type family Same (b :: Bool) (r :: k) (rq :: [k]) :: k where
  Same bool r (x ': xs) = Same (bool :&& (r == x)) r xs
  Same bool r '[] = TP bool r

data NotEqualFailure
-- converts a True result to a type
type family EqResult tp where
  EqResult (TP 'True r) = r
  EqResult (TP 'False r) = NotEqualFailure



data Zq q i
type family Foo rq
type instance Foo (Zq q i) = i
type R = 
  EqResult 
    (Same 'True (Foo (Zq Double Int)) 
      (Map (TyCon1 Foo) 
        '[Zq Double Int, Zq Float Int]))

f :: R
f = 3

这不在GHC 7.8.3中编译:

No instance for (Num NotEqualFailure)
      arising from a use of ‘f’
    In the expression: f
    In an equation for ‘it’: it = f

但如果我注释掉f并启动GHCi:

> :kind! R
R :: *
= Int

所以GHC似乎无法决定我的列表中的元素是否相等。如果它们相等,则EqResult应返回公共类型(此处为Int),否则返回NotEqualFailure。谁能解释一下这里发生了什么?如果你认为这看起来像一个bug,请告诉我,我将把它归档到GHC trac。

如果你能找到一种方法来写" EqResult(相同......)"以不同的方式,它可能解决这个问题。


修改 我改写了类型系列,但遗憾的是我的问题基本相同。代码现在更小更简单。

{-# LANGUAGE TypeFamilies, TypeOperators, DataKinds, FlexibleContexts, UndecidableInstances #-}

module Foo where

import Data.Singletons.Prelude
import Data.Singletons.Prelude.List
import Data.Type.Equality

-- foldl (\(bool, r) x -> (bool && (r == x), r)) (True, head xs) xs
type family Same rq where
  Same (x ': xs) = 
    EqResult (And (Map ((TyCon2 (==)) $ x) xs)) x

data NotEqualFailure
-- converts a True result to a type
type family EqResult b v where
  EqResult 'True r = r
  EqResult 'False r = NotEqualFailure

type R = Same '[Int, Int]

f :: R
f = 3

GHCi仍然可以解析RInt,但GHC现在根本无法解析EqResult的类型系列(在错误地将其解析为{{1}之前) })。请注意,如果我将列表的大小更改为1,即NotEqualFailure,则此示例有效。


编辑2 我删除了所有外部库,并使一切工作正常。这个解决方案可能是最小的,但我仍然想知道为什么更大的例子似乎打破了GHC。

'[Int]

1 个答案:

答案 0 :(得分:3)

实际上存在一个错误,并且在GHC的下一个版本中它是will be fixed