I am curious if it is possible to write a function apply_nth
that takes a function, the number of a parameter, and that parameter's value and then returns a new, partially-applied function.
The feeling I get is that this is impossible due to the type system, but I can't come up with a satisfying answer. I also can't come up with a working type signature.
If the language were more loosely-typed, I imagine the code might look like this.
apply_nth f 0 x = f x
apply_nth f n x = \a -> apply_nth (f a) (n-1) x
Any ideas?
Not that weird type families, but not super nice either:
{-# LANGUAGE GADTs, DataKinds, TypeFamilies, TypeOperators #-}
import Data.Proxy
type family Fun as b where
Fun '[] b = b
Fun (a ': as) b = a -> Fun as b
data SL as where
Sn :: SL '[]
Sc :: SL as -> SL (a ': as)
applyN :: Proxy c -> SL as -> Fun as (b -> c) -> b -> Fun as c
applyN p Sn f y = f y
applyN p (Sc s) f y = \x -> applyN p s (f x) y
main = print $ applyN Proxy (Sc (Sc Sn)) zipWith [1,2,3] (-) [6,5,4] -- [5,3,1]
We can also package Proxy c
into SL
:
data SL as c where
Sn :: SL '[] c
Sc :: SL as c -> SL (a ': as) c
applyN :: SL as c -> Fun as (b -> c) -> b -> Fun as c
applyN Sn f y = f y
applyN (Sc s) f y = \x -> applyN s (f x) y
main = print $ applyN (Sc (Sc Sn)) zipWith [1,2,3] (-) [6,5,4] -- [5,3,1]
Or you can simply define a few combinators:
z = id
s r f y x = r (f x) y
applyN = id
main = print $ applyN (s (s z)) zipWith [1,2,3] (-) [6,5,4] -- [5,3,1]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With