尝试开发一个递归类型级函数来派生函数输入和输出

时间:2013-07-28 04:29:15

标签: haskell typeclass gadt data-kinds

以下定义需要了解我的要求:

data Param = PA | PB | PC

data R p a where
  A :: S a -> R PA (S a)
  B :: S a -> R PB (S a)

data S a where
  Prim :: a -> S a
  HO   :: R pa a -> R pb b -> S ((R pa a) -> (R pb b))
  Pair :: R pa a -> R pb b -> S ((R pa a), (R pb b))

data Box r a = Box r a  

我想使用这些定义编写一个函数,其工作方式如下:

trans :: t -> TransIn t -> TransOut t

,其中

TransIn (R 'PA (S a)) = a
TransIn (R 'PB (S a)) = a
TransIn (R 'PA (S (r1, r2))) = (TransIn r1, TransIn r2)
TransIn (R 'PA (S (r1, r2))) = (TransIn r1, TransIn r2)
TransIn (R 'PA (S (r1 -> r2))) = Error
TransIn (R 'PB (S (r1 -> r2))) = TransOut r1 -> TransIn r2

TransOut (R 'PA (S a)) = Box (R 'PA (S a)) a
TransOut (R 'PB (S a)) = Box (R 'PB (S a)) a
TransOut (R 'PA (S (r1, r2))) = (TransOut r1, TransOut r2)
TransOut (R 'PA (S ((R p (S a)), R p (S b))))) = (Box (R p (S a)) a, Box (R p (S b)) b)
TransOut (R 'PA (S (r1 -> r2))) = Error
TransOut (R 'PB (S (r1 -> r2))) = TransIn r1 -> TransOut r2

基本思想是接受不同形状的输入,并根据用于S的构造函数和构建R时选择的参数生成不同形状的输出。我一直在尝试使用具有数据类的类来执行此操作,但是我我遇到了错误的错误。我想知道是否有一种直观,干净的方式来编码这种类型的东西。

我目前的尝试如下:

class Transform t a where
  data TransIn t a:: *
  data TransOut t a:: *
  trans :: t -> TransIn t a -> TransOut t a

instance Transform (R Param (S a)) a where
  data TransIn (A (S a)) a :: a
  data TransOut (A (S a)) a :: Box (R Param (S a)) a
  trans t a = Box t a

instance Transform (R Param (S (a -> b))) a where
  data TransIn (A (S (a -> b))) (a -> b) :: TransIn a -> TransIn b
  data TransOut (A (S (a -> b))) (a -> b) :: TransOut a -> TransOut b
  trans _ _ = undefined

这种方法抱怨R的第一个参数应该有类Param,但Param有类型*,我不知道如何纠正这个。添加约束并使用变量时,我到了这里:

instance (p :: Param) => Transform (R p (S a)) a where
  data TransIn (R p (S a))) a :: a
  data TransOut (R p (S a)) a :: Box (R p (S a)) a
  trans t a = Box t a

当然,Haskell拒绝让我使用Kind作为约束。我很迷茫,我不知道该去哪儿。任何帮助或指导都是非常宝贵的。

1 个答案:

答案 0 :(得分:1)

我将从单参数类型类开始,其中包含两个关联类型系列TransInTransOut

class Transform t where
  type TransIn t
  type TransOut t
  trans :: t -> TransIn t -> TransOut t

现在,TypeInTypeOut的六个等式需要六个实例。这是第一个。

instance Transform (R PA (S a)) where
  type TransIn (R PA (S a)) = a
  type TransOut (R PA (S a)) = Box (R PA (S a)) a
  trans t a = error "implement me!"

请注意,TransInTransOut的定义实际上是问题中的等式。