{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
module Symantic.Base.CurryN where
import Data.Function (($), (.))
import Symantic.Base.ADT (Tuples)
class CurryN args where
curryN :: (Tuples args -> res) -> args-..->res
uncurryN :: (args-..->res) -> Tuples args -> res
mapresultN :: (a->b) -> (args-..->a) -> args-..->b
instance CurryN '[a] where
curryN = ($)
uncurryN = ($)
mapresultN = (.)
instance CurryN (b ': as) => CurryN (a ': b ': as) where
curryN f x = curryN @(b ': as) (\xs -> f (x, xs))
uncurryN f (x, xs) = uncurryN @(b ': as) (f x) xs
mapresultN f as2r = mapresultN @(b ': as) f . as2r
type family (args :: [*]) -..-> (r :: *) :: * where
'[] -..-> r = r
(a : args) -..-> r = a -> args -..-> r
type family Args (f :: *) :: [*] where
Args (a -> r) = a : Args r
Args r = '[]
type family Result (as :: *) :: * where
Result (a -> r) = Result r
Result r = r