{-# LANGUAGE IncoherentInstances, OverlappingInstances, TypeFamilies, FlexibleInstances, MultiParamTypeClasses, UndecidableInstances, ScopedTypeVariables #-} module Curried where class Curry f args result where curryP :: (args -> result) -> f class Uncurry f args result where uncurryP :: f -> (args -> result) instance (Curry rf as result, f ~ (a -> rf)) => Curry f (a, as) result where curryP c x = curryP (\as -> c (x, as)) instance (Uncurry b as result, args ~ (a, as)) => Uncurry (a -> b) args result where uncurryP f (a, as) = uncurryP (f a) as
module Main where import Curried instance (f ~ result) => Curry f () result where curryP c = c () instance (args ~ (), result ~ f) => Uncurry f args result where uncurryP f () = f ($.) :: forall f g a b c. (Uncurry f a b, Curry g a c) => (b -> c) -> f -> g f $. g = curryP (\x -> f (uncurryP g (x :: a))) -- テスト main = print $ ((+1) $. const) 100 200