不具备n-ary功能

时间:2014-07-19 17:44:51

标签: haskell ghc type-families

我有一个类型级别编号

data Z   deriving Typeable
data S n deriving Typeable

和n-ary函数(来自固定向量包的代码)

-- | Type family for n-ary functions.
type family   Fn n a b
type instance Fn Z     a b = b
type instance Fn (S n) a b = a -> Fn n a b

-- | Newtype wrapper which is used to make 'Fn' injective. It's also a
--   reader monad.
newtype Fun n a b = Fun { unFun :: Fn n a b }

我需要像

这样的功能
uncurryN :: Fun (n + k) a b -> Fun n a (Fun k a b)

我阅读了几篇关于类型级别计算的文章,但都是关于类型安全列表连接的文章。

1 个答案:

答案 0 :(得分:4)

这需要在解开/重新包装Fun newtype时要小心。我还利用了DataKinds扩展名。

{-# LANGUAGE DataKinds, KindSignatures, TypeFamilies, 
    MultiParamTypeClasses, ScopedTypeVariables, FlexibleInstances #-}
{-# OPTIONS -Wall #-}

-- | Type-level naturals.
data Nat = Z | S Nat

-- | Type family for n-ary functions.
type family   Fn (n :: Nat) a b
type instance Fn Z     a b = b
type instance Fn (S n) a b = a -> Fn n a b

-- | Addition.
type family   Add (n :: Nat) (m :: Nat) :: Nat
type instance Add Z          m = m
type instance Add (S n)      m = S (Add n m)

-- | Newtype wrapper which is used to make 'Fn' injective.
newtype Fun n a b = Fun { unFun :: Fn n a b }

class UncurryN (n :: Nat) (m :: Nat) a b where
    uncurryN :: Fun (Add n m) a b -> Fun n a (Fun m a b)

instance UncurryN Z m a b where
    uncurryN g = Fun g

instance UncurryN n m a b => UncurryN (S n) m a b where
    uncurryN g = Fun (\x -> unFun (uncurryN (Fun (unFun g x)) :: Fun n a (Fun m a b)))

{- An expanded equivalent with more signatures:

instance UncurryN n m a b => UncurryN (S n) m a b where
    uncurryN g = let f :: a -> Fn n a (Fun m a b)
                     f x = let h :: Fun (Add n m) a b
                               h = Fun ((unFun g :: Fn (Add (S n) m) a b) x)
                           in unFun (uncurryN h :: Fun n a (Fun m a b))
                     in Fun f
-}