実装したい(2)

GHCのバージョンは6.10.4です。

{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE UndecidableInstances #-}

data COP a b
data App b

class TyEq a b | a -> b where
    f :: a -> b
    f v = undefined
instance TyEq Int Int
instance TyEq (App b) b
instance TyEq (COP a b) a
instance (TyEqProxy a a') => TyEq a a'

s1 :: Int
s1 = undefined
s2 :: App a
s2 = undefined
s3 :: COP a b
s3 = undefined
s4 :: a 
s4 = undefined

class TyEqProxy a b | a -> b
instance TyEqProxy a a

data Exp t where
    EInt :: Int -> Exp Int
    ELam :: (Exp a -> Exp b) -> Exp (a -> b)
    EApp :: (TyEq t t',t' ~ a) => Exp (a -> b) -> Exp t -> Exp (App b)
    Cop :: (TyEq c c',c' ~ b) => Exp ((a -> b) -> c) -> Exp (COP a b)

e1 :: Exp Int
e1 = EInt 1

e2 :: Exp (Int -> Int)
e2 = ELam (\(EInt x) -> EInt (x + 1))

e3 :: Exp (App Int)
e3 = EApp e2 e1

aux_e4 :: Exp (COP Int b)
aux_e4 = Cop (ELam (\k -> EApp k (EInt 2)))

e4 :: Exp (App Int)
e4 = EApp e2 aux_e4

exit :: Exp (a -> b)
exit = ELam exit'
    where
      exit' :: Exp a -> Exp b
      exit' v = error "exit"

class CPS cps_a cps_b where
    type Kont1 cps_a cps_b
    type Kont2 cps_a cps_b
    cps :: cps_a -> Kont1 cps_a cps_b -> Kont2 cps_a cps_b

instance CPS (Exp (App a')) (Exp b') where
    type Kont1 (Exp (App a')) (Exp b') = Exp (a' -> b')
    type Kont2 (Exp (App a')) (Exp b') = Exp b'
    cps (EApp (f :: Exp (arg -> b)) (arg :: Exp c) :: Exp (App a')) (ELam k) = undefined
        where
          k' :: Exp a' -> Exp b'
          k' = k

{-
          k1_body :: Exp (arg -> b) -> Exp b'
          k1_body = (\(f' :: Exp (arg -> b)) -> case f' of
                                                  ELam f'' -> k2_body f''
                    )
-}

          -- k2_body :: (Exp arg -> Exp b) -> Exp b'
          k2_body :: (CPS (Exp c) b,Kont1 (Exp c) b ~ Exp (a -> b')) => (Exp a -> Exp a') -> Kont2 (Exp c) b
          k2_body (f'' :: Exp a -> Exp a') = cps
                                             (arg :: Exp c)
                                             (ELam
                                              (\(arg' :: Exp a) ->
                                                   ((k'
                                                     ((f'' arg') :: Exp a')) :: Exp b'
                                                   )
                                              )
                                              :: Exp (a -> b'))
cont4.hs:89:45:
    Could not deduce (CPS (Exp t) cps_b)
      from the context (Kont1 (Exp t) b ~ Exp (a2 -> b'),
                        CPS (Exp t) cps_b1,
                        CPS (Exp t) b)
      arising from a use of `cps' at cont4.hs:(89,45)-(97,62)
    Possible fix:
      add (CPS (Exp t) cps_b) to the context of
        the type signature for `k2_body'
      or add an instance declaration for (CPS (Exp t) cps_b)

その他...

と言われるが、cps_bってどこから引っ張って来たら良いんだろう。

あともう兎に角前に進もうって感じで書いているので、相当メチャクチャになってる...

ただ、ghciでこいつを推論させる事自体は出来ているらしくて・・・ううーん・・・。
ghci -ddump-tc で吐かせてもrenameされちゃってて良く分からない(なので、型をそのままコピペしても駄目)

ddump-tcに従って見ると

          k2_body :: forall a cps_b.(Exp (a -> b') ~ Kont1 (Exp c) cps_b,CPS (Exp c) cps_b) =>
                              (Exp a -> Exp a') -> Kont2 (Exp c) cps_b
          k2_body f'' = cps
                        (arg :: Exp c)
                        (ELam
                         (\arg' ->
                              (k'
                                (f'' arg')
                              )
                         )
                        )

これでいけるはずだけれども、駄目と言われてしまう。うーん...??

同様の問題(なのか、それとも単に私が間違ってる気もするのですが)が発生するもっと小さいコードを作ってみようか。