Currying function using values from array

Dear Haskell experts, I am currently studying Groovy language. An experiment I did with its closure is to perform closure/function "curry" using an array containing the values for the parameter binding. See the sample below. int addThemUp(a,b,c,d,e) { a+b+c+d+e } def arrayCurry(arr, cls) { arr.inject(cls) { c, v -> c.curry(v) } } println addThemUp(1,2,3,4,5) println arrayCurry([1,2,3,4,5], this.&addThemUp)() println arrayCurry([1,2,3,4], this.&addThemUp)(5) The printouts from the above code are the same, verifying that the code works fine. Then I come to ask myself how I can do the same in Haskell. I'm not a Haskell expert so I couldn't figure it. I wonder if you guys could shed some light on this. Thanks, Ed

On Thu, 7 Aug 2008, Sukit Tretriluxana wrote:
Dear Haskell experts,
I am currently studying Groovy language. An experiment I did with its closure is to perform closure/function "curry" using an array containing the values for the parameter binding. See the sample below.
int addThemUp(a,b,c,d,e) { a+b+c+d+e } def arrayCurry(arr, cls) { arr.inject(cls) { c, v -> c.curry(v) } } println addThemUp(1,2,3,4,5) println arrayCurry([1,2,3,4,5], this.&addThemUp)() println arrayCurry([1,2,3,4], this.&addThemUp)(5)
The printouts from the above code are the same, verifying that the code works fine. Then I come to ask myself how I can do the same in Haskell. I'm not a Haskell expert so I couldn't figure it. I wonder if you guys could shed some light on this.
I do not know Groovy, but maybe you want something like addThemUp :: Num a => (a,a,a,a,a) -> a addThemUp (a,b,c,d,e) = a+b+c+d+e -- should be better named list5Curry or so arrayCurry :: ((a,a,a,a,a) -> a) -> [a] -> a arrayCurry cls [a,b,c,d,e] = cls (a,b,c,d,e) print (addThemUp(1,2,3,4,5::Int)) print (arrayCurry addThemUp [1,2,3,4,5::Int]) However, it's hardly of any use, since you won't use a list if the number of elements is fixed (and small) or if the elements even must have distinct types.

Maybe you want something like
curryWithList :: ([a]->b)->[a]->([a]->b)
curryWithList f lst1= \lst2 ->f (lst1++lst2)
addThemUp = sum
curried = curryWithList addThemUp [1,2,3,4]
curried [5] =15
On Thu, Aug 7, 2008 at 8:35 PM, Henning Thielemann
On Thu, 7 Aug 2008, Sukit Tretriluxana wrote:
Dear Haskell experts,
I am currently studying Groovy language. An experiment I did with its closure is to perform closure/function "curry" using an array containing the values for the parameter binding. See the sample below.
int addThemUp(a,b,c,d,e) { a+b+c+d+e } def arrayCurry(arr, cls) { arr.inject(cls) { c, v -> c.curry(v) } } println addThemUp(1,2,3,4,5) println arrayCurry([1,2,3,4,5], this.&addThemUp)() println arrayCurry([1,2,3,4], this.&addThemUp)(5)
The printouts from the above code are the same, verifying that the code works fine. Then I come to ask myself how I can do the same in Haskell. I'm not a Haskell expert so I couldn't figure it. I wonder if you guys could shed some light on this.
I do not know Groovy, but maybe you want something like
addThemUp :: Num a => (a,a,a,a,a) -> a addThemUp (a,b,c,d,e) = a+b+c+d+e
-- should be better named list5Curry or so arrayCurry :: ((a,a,a,a,a) -> a) -> [a] -> a arrayCurry cls [a,b,c,d,e] = cls (a,b,c,d,e)
print (addThemUp(1,2,3,4,5::Int)) print (arrayCurry addThemUp [1,2,3,4,5::Int])
However, it's hardly of any use, since you won't use a list if the number of elements is fixed (and small) or if the elements even must have distinct types. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Thanks Tom and Henning for your response. Let me put the question in another
way by generalizing and tweaking it a little bit.
How in Haskell that I can create a function that curries *any *other
function, which receives multiple parameters, by using a the input from a
list (same data type) or a tuple (mixed data type) such that it either
returns another closure (if not all parameters are curried) or the final
value of the computation (when all parameters are known)?
Ed
On Thu, Aug 7, 2008 at 12:49 PM, Tom Nielsen
Maybe you want something like
curryWithList :: ([a]->b)->[a]->([a]->b) curryWithList f lst1= \lst2 ->f (lst1++lst2)
addThemUp = sum curried = curryWithList addThemUp [1,2,3,4] curried [5] =15
On Thu, Aug 7, 2008 at 8:35 PM, Henning Thielemann
wrote: On Thu, 7 Aug 2008, Sukit Tretriluxana wrote:
Dear Haskell experts,
I am currently studying Groovy language. An experiment I did with its closure is to perform closure/function "curry" using an array containing
the
values for the parameter binding. See the sample below.
int addThemUp(a,b,c,d,e) { a+b+c+d+e } def arrayCurry(arr, cls) { arr.inject(cls) { c, v -> c.curry(v) } } println addThemUp(1,2,3,4,5) println arrayCurry([1,2,3,4,5], this.&addThemUp)() println arrayCurry([1,2,3,4], this.&addThemUp)(5)
The printouts from the above code are the same, verifying that the code works fine. Then I come to ask myself how I can do the same in Haskell. I'm not a Haskell expert so I couldn't figure it. I wonder if you guys could shed some light on this.
I do not know Groovy, but maybe you want something like
addThemUp :: Num a => (a,a,a,a,a) -> a addThemUp (a,b,c,d,e) = a+b+c+d+e
-- should be better named list5Curry or so arrayCurry :: ((a,a,a,a,a) -> a) -> [a] -> a arrayCurry cls [a,b,c,d,e] = cls (a,b,c,d,e)
print (addThemUp(1,2,3,4,5::Int)) print (arrayCurry addThemUp [1,2,3,4,5::Int])
However, it's hardly of any use, since you won't use a list if the number of elements is fixed (and small) or if the elements even must have distinct types. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hello Sukit, Friday, August 8, 2008, 3:52:51 AM, you wrote: it requires use of typeclasses instance C f => C (a->f) curry (somef::(a->f)) (someas::[a]) = (somef (head someas)) (tail someas) and so on. look into hslua sources, for example: http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hslua
Thanks Tom and Henning for your response. Let me put the question in another way by generalizing and tweaking it a little bit.
How in Haskell that I can create a function that curries any other function, which receives multiple parameters, by using a the input from a list (same data type) or a tuple (mixed data type) such that it either returns another closure (if not all parameters are curried) or the final value of the computation (when all parameters are known)?
Ed
On Thu, Aug 7, 2008 at 12:49 PM, Tom Nielsen
wrote: Maybe you want something like curryWithList :: ([a]->b)->[a]->([a]->b) curryWithList f lst1= \lst2 ->f (lst1++lst2)
addThemUp = sum curried = curryWithList addThemUp [1,2,3,4] curried [5] =15
On Thu, Aug 7, 2008 at 8:35 PM, Henning Thielemann
wrote: On Thu, 7 Aug 2008, Sukit Tretriluxana wrote:
Dear Haskell experts,
I am currently studying Groovy language. An experiment I did with its closure is to perform closure/function "curry" using an array containing the values for the parameter binding. See the sample below.
int addThemUp(a,b,c,d,e) { a+b+c+d+e } def arrayCurry(arr, cls) { arr.inject(cls) { c, v -> c.curry(v) } } println addThemUp(1,2,3,4,5) println arrayCurry([1,2,3,4,5], this.&addThemUp)() println arrayCurry([1,2,3,4], this.&addThemUp)(5)
The printouts from the above code are the same, verifying that the code works fine. Then I come to ask myself how I can do the same in Haskell. I'm not a Haskell expert so I couldn't figure it. I wonder if you guys could shed some light on this.
I do not know Groovy, but maybe you want something like
addThemUp :: Num a => (a,a,a,a,a) -> a addThemUp (a,b,c,d,e) = a+b+c+d+e
-- should be better named list5Curry or so arrayCurry :: ((a,a,a,a,a) -> a) -> [a] -> a arrayCurry cls [a,b,c,d,e] = cls (a,b,c,d,e)
print (addThemUp(1,2,3,4,5::Int)) print (arrayCurry addThemUp [1,2,3,4,5::Int])
However, it's hardly of any use, since you won't use a list if the number of elements is fixed (and small) or if the elements even must have distinct types.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

2008/8/7 Sukit Tretriluxana
How in Haskell that I can create a function that curries any other function, which receives multiple parameters, by using a the input from a list (same data type) or a tuple (mixed data type) such that it either returns another closure (if not all parameters are curried) or the final value of the computation (when all parameters are known)?
Here's a solution that uses tuples only (no lists, they are somewhat more difficult to typecheck correctly), along with several tests. The payoff is functions with signatures like this: -- tncurry :: (a -> b -> c -> r) -> (a,b,c) -> r -- trcurry :: ((a,b,c) -> r) -> a -> b -> c -> r -- ncurry :: (a -> b -> c -> r) -> (a, (b, (c, ()))) -> r -- rcurry :: ((a, (b, (c, ()))) -> r) -> a -> b -> c -> r but that work on any number of arguments. (disclaimer: I've only implemented tncurry & trcurry up to 4-tuples; additional tuple sizes require 3 lines of boilerplate code each). -- ryan {-# OPTIONS_GHC -fglasgow-exts -fallow-undecidable-instances -fno-monomorphism-restriction #-} module Curry where -- no-monomorphism-restriction is just so we don't -- have to put dummy arguments on the tests. class IsFunction f a r | f -> a r, a r -> f where apply :: f -> a -> r instance IsFunction (a -> b) a b where apply = ($) class NCurry f a r | f a -> r where ncurry :: f -> a -> r instance NCurry r () r where ncurry x _ = x instance (IsFunction f' b f, NCurry f a r) => NCurry f' (b,a) r where ncurry f (b,a) = ncurry (apply f b) a class RCurry t x r | t x -> r where rcurry :: (t -> x) -> r instance RCurry () r r where rcurry f = f () instance RCurry t x r => RCurry (a,t) x (a -> r) where rcurry f x = rcurry (\t -> f (x,t)) -- some tests test1 = ncurry (+) (5, (10, ())) -- test1 :: Num f => f -- test1 => 15 plus :: Num a => (a, (a, ())) -> a plus = ncurry (+) test2 = rcurry plus -- test2 :: Num a => a -> a -> a test_broken = rcurry (ncurry (+)) -- test_broken :: (Num a, NCurry (a -> a -> a) t r, RCurry t r r1) => r1 {- test_broken 5 10 => No instances for (NCurry (a -> a -> a) t r, RCurry t r (t1 -> t2 -> t3)) This is an instance of the "read.show" problem; ncurry (+) has many types: ncurry (+) :: Num a => () -> a -> a -> a ncurry (+) :: Num a => (a,()) -> a -> a ncurry (+) :: Num a => (a,(a,())) -> a Even though rcurry would work on any of these, it's ambiguous which one to choose, so the type inferencer gives up. -} test3 = test2 5 10 -- test3 :: Num t => t -- test3 => 15 -- stupid constant function dumb a b c d = c test4 = ncurry dumb ("wrong", (5, ("correct", ([1..50], ())))) -- test4 :: [Char] -- test4 => "correct" dumb2 (a, (b, (c, (d, ())))) = c test5 = rcurry dumb2 -- test5 :: t -> t1 -> r -> t2 -> r test6 = rcurry dumb2 "wrong" 5 "correct" [1..50] -- test6 :: [Char] -- test6 => "correct" -- We can also use "real" tuples instead of tuple-lists, with -- some boilerplate... class TupleChange n t | n -> t, t -> n where toTuple :: n -> t fromTuple :: t -> n -- Haskell doesn't have a "1-tuple", so make it ourselves data Tuple1 x = Tuple1 x deriving (Eq, Show, Ord) instance TupleChange () () where toTuple = id fromTuple = id instance TupleChange (a, ()) (Tuple1 a) where toTuple (a, ()) = Tuple1 a fromTuple (Tuple1 a) = (a, ()) instance TupleChange (a, (b, ())) (a, b) where toTuple (a, (b, ())) = (a,b) fromTuple (a,b) = (a, (b, ())) instance TupleChange (a, (b, (c, ()))) (a,b,c) where toTuple (a, (b, (c, ()))) = (a,b,c) fromTuple (a,b,c) = (a, (b, (c, ()))) instance TupleChange (a, (b, (c, (d, ())))) (a,b,c,d) where toTuple (a, (b, (c, (d, ())))) = (a,b,c,d) fromTuple (a,b,c,d) = (a, (b, (c, (d, ())))) tncurry f = ncurry f . fromTuple trcurry f = rcurry (f . toTuple) -- Tests of tncurry/trcurry & show closures test7 = tncurry (+) (Tuple1 5) -- test7 :: Num a => a -> a -- test7 10 => 15 dumb3 (a,b,c,d) = c test8 = trcurry dumb3 -- test8 :: t -> t1 -> r -> t2 -> r -- test9 creates a closure waiting for more -- arguments... test9 = tncurry dumb ("foo", "bar", "hat") -- test9 :: t -> [Char] -- test9 "baz" => "hat" -- although you do have to use tncurry again -- with each call if you want to keep applying -- it with tuples test10 = tncurry (tncurry dumb ("foo", "bar", "hat")) (Tuple1 "baz") -- test10 :: [Char] -- test10 => "hat"

Sukit Tretriluxana schrieb:
Thanks Tom and Henning for your response. Let me put the question in another way by generalizing and tweaking it a little bit.
How in Haskell that I can create a function that curries *any *other function, which receives multiple parameters, by using a the input from a list (same data type) or a tuple (mixed data type) such that it either returns another closure (if not all parameters are curried) or the final value of the computation (when all parameters are known)?
Is this a theoretical question or do you actually need this? If yes, I wonder what application it may be.

Thanks so much for the response so far. To Lemming's question, this is just
a theoretical question. I try comparing what I can do in Groovy with
Haskell. So far I could come up with solutions but not this one. I'm not an
expert on this but I'm not sure if template haskell or type class would come
to rescue this situation. And if so, I wonder how it looks like.
Ed
On Fri, Aug 8, 2008 at 2:39 PM, Lemming
Sukit Tretriluxana schrieb:
Thanks Tom and Henning for your response. Let me put the question in another way by generalizing and tweaking it a little bit.
How in Haskell that I can create a function that curries *any *other function, which receives multiple parameters, by using a the input from a list (same data type) or a tuple (mixed data type) such that it either returns another closure (if not all parameters are curried) or the final value of the computation (when all parameters are known)?
Is this a theoretical question or do you actually need this? If yes, I wonder what application it may be.
participants (6)
-
Bulat Ziganshin
-
Henning Thielemann
-
Lemming
-
Ryan Ingram
-
Sukit Tretriluxana
-
Tom Nielsen