Skip to content

Commit

Permalink
Merge pull request #34 from Shimuuar/generalize-arity
Browse files Browse the repository at this point in the history
Add more general methods to ArityPeano type class
  • Loading branch information
Shimuuar authored Dec 19, 2024
2 parents f65da8b + a5b67a8 commit 4db1a55
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 45 deletions.
3 changes: 3 additions & 0 deletions fixed-vector/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ Changes in 1.3.0.0

- `CVecPeano` dropped and `ContVec` is parameterized using Peano numbers.

* In `ArityPeano` type class methods `reverseF` and `gunfoldF` are replaced
with more general `accumPeano` and `reducePeano`.

* `Data.Vector.Fixed.Cont.arity` dropped

* Type of `D.V.F.Cont.withFun` generalized
Expand Down
99 changes: 54 additions & 45 deletions fixed-vector/Data/Vector/Fixed/Cont.hs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,14 @@ class ArityPeano n where
-> t n -- ^ Initial value
-> Fun n a b -- ^ Reduction function

-- | Same as @accum@ but allow use @ArityPeano@ at each step Note
-- that in general case this will lead to /O(n²)/ compilation time.
accumPeano
:: (forall k. ArityPeano k => t ('S k) -> a -> t k) -- ^ Fold function
-> (t 'Z -> b) -- ^ Extract result of fold
-> t n -- ^ Initial value
-> Fun n a b -- ^ Reduction function

-- | Apply all parameters to the function.
applyFun :: (forall k. t ('S k) -> (a, t k))
-- ^ Get value to apply to function
Expand All @@ -247,18 +255,16 @@ class ArityPeano n where
-> t n -- ^ Initial value
-> (f (ContVec n a), t 'Z)


-- | Perform N reduction steps. This function doesn't involve N-ary
-- function directly.
reducePeano :: (forall k. t ('S k) -> t k) -- ^ Reduction step
-> t n
-> t 'Z

-- | Conver peano number to int
peanoToInt :: Proxy# n -> Int

-- | Reverse order of parameters. It's implemented directly in type
-- class since expressing it in terms of @accum@ will require
-- putting Arity constraint on step funcion
reverseF :: Fun n a b -> Fun n a b

-- | Worker function for 'gunfold'
gunfoldF :: (Data a)
=> (forall b x. Data b => c (b -> x) -> c x)
-> T_gunfold c r a n -> c r
-- | Provide @ArityPeano@ dictionary for previous Peano number. GHC
-- cannot infer that when @ArityPeano n@ and @n ~ S k@ we have
-- instance for @k@ as well. So we have to provide such dictionary
Expand Down Expand Up @@ -298,37 +304,36 @@ class Index (k :: PeanoNum) (n :: PeanoNum) where


instance ArityPeano 'Z where
accum _ g t = Fun $ g t
applyFun _ t = (ContVec unFun, t)
applyFunM _ t = (pure (ContVec unFun), t)
peanoToInt _ = 0
{-# INLINE accum #-}
{-# INLINE applyFun #-}
{-# INLINE applyFunM #-}
accum _ g t = Fun $ g t
accumPeano _ g t = Fun $ g t
applyFun _ t = (ContVec unFun, t)
applyFunM _ t = (pure (ContVec unFun), t)
reducePeano _ = id
peanoToInt _ = 0
{-# INLINE accum #-}
{-# INLINE accumPeano #-}
{-# INLINE applyFun #-}
{-# INLINE applyFunM #-}
{-# INLINE reducePeano #-}
{-# INLINE peanoToInt #-}
reverseF = id
gunfoldF _ (T_gunfold c) = c
{-# INLINE reverseF #-}
{-# INLINE gunfoldF #-}
dictionaryPred _ _ = error "dictionaryPred: IMPOSSIBLE"

instance ArityPeano n => ArityPeano ('S n) where
accum f g t = Fun $ \a -> unFun $ accum f g (f t a)
applyFun f t = let (a,t') = f t
(v,tZ) = applyFun f t'
in (consPeano a v, tZ)
applyFunM f t = let (a,t') = f t
(vec,t0) = applyFunM f t'
in (consPeano <$> a <*> vec, t0)
peanoToInt _ = 1 + peanoToInt (proxy# @n)
accum f g t = Fun $ \a -> unFun $ accum f g (f t a)
accumPeano f g t = Fun $ \a -> unFun $ accumPeano f g (f t a)
applyFun f t = let (a,t') = f t
(v,tZ) = applyFun f t'
in (consPeano a v, tZ)
applyFunM f t = let (a,t') = f t
(vec,t0) = applyFunM f t'
in (consPeano <$> a <*> vec, t0)
reducePeano f t = reducePeano f (f t)
peanoToInt _ = 1 + peanoToInt (proxy# @n)
{-# INLINE accum #-}
{-# INLINE applyFun #-}
{-# INLINE applyFunM #-}
{-# INLINE peanoToInt #-}
reverseF f = Fun $ \a -> unFun (reverseF $ apLast f a)
gunfoldF f c = gunfoldF f (apGunfold f c)
{-# INLINE reverseF #-}
{-# INLINE gunfoldF #-}
{-# INLINE reducePeano #-}
dictionaryPred _ r = r
{-# INLINE dictionaryPred #-}

Expand All @@ -352,15 +357,6 @@ instance Index k n => Index (S k) (S n) where



apGunfold :: Data a
=> (forall b x. Data b => c (b -> x) -> c x)
-> T_gunfold c r a ('S n)
-> T_gunfold c r a n
apGunfold f (T_gunfold c) = T_gunfold $ f c
{-# INLINE apGunfold #-}



----------------------------------------------------------------
-- Combinators
----------------------------------------------------------------
Expand Down Expand Up @@ -862,6 +858,16 @@ reverse :: ArityPeano n => ContVec n a -> ContVec n a
reverse (ContVec cont) = ContVec $ cont . reverseF
{-# INLINE reverse #-}

reverseF :: forall n a b. ArityPeano n => Fun n a b -> Fun n a b
reverseF (Fun fun0) = accumPeano
step
(\(T_map b) -> b)
(T_map fun0 :: T_map a b n)
where
step :: forall k. ArityPeano k => T_map a b (S k) -> a -> T_map a b k
step (T_map f) a = T_map $ unFun $ apLast (Fun f :: Fun (S k) a b) a


-- | Zip two vector together using function.
zipWith :: (ArityPeano n) => (a -> b -> c)
-> ContVec n a -> ContVec n b -> ContVec n c
Expand Down Expand Up @@ -1211,12 +1217,15 @@ gunfold :: forall con c v a. (Vector v a, Data a)
=> (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r)
-> con -> c (v a)
gunfold f inj _
= gunfoldF f gun
gunfold f inj _ =
case reducePeano step gun of
T_gunfold c -> c
where
con = construct :: Fun (Dim v) a (v a)
con = construct @v @a
gun = T_gunfold (inj $ unFun con) :: T_gunfold c (v a) a (Dim v)

--
step :: forall k r. T_gunfold c r a ('S k) -> T_gunfold c r a k
step (T_gunfold c) = T_gunfold (f c)

gfoldlF :: (ArityPeano n, Data a)
=> (forall x y. Data x => c (x -> y) -> x -> c y)
Expand Down

0 comments on commit 4db1a55

Please sign in to comment.