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 _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
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 [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
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 <[hidden email]> 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 > [hidden email] > http://www.haskell.org/mailman/listinfo/haskell-cafe > Haskell-Cafe mailing list [hidden email] 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 <[hidden email]> wrote: Maybe you want something like _______________________________________________ Haskell-Cafe mailing list [hidden email] 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 <[hidden email]> 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 > <[hidden email]> 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 >> [hidden email] >> http://www.haskell.org/mailman/listinfo/haskell-cafe >> > > -- Best regards, Bulat mailto:[hidden email] _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Sukit Tretriluxana
2008/8/7 Sukit Tretriluxana <[hidden email]>:
> 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" _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Sukit Tretriluxana
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. _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
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 <[hidden email]> wrote: Sukit Tretriluxana schrieb: _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
Free forum by Nabble | Edit this page |