Currying function using values from array

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Currying function using values from array

Sukit Tretriluxana
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
Reply | Threaded
Open this post in threaded view
|

Re: Currying function using values from array

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
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Currying function using values from array

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
<[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
Reply | Threaded
Open this post in threaded view
|

Re: Currying function using values from array

Sukit Tretriluxana
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
>


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re[2]: Currying function using values from array

Bulat Ziganshin-2
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
Reply | Threaded
Open this post in threaded view
|

Re: Currying function using values from array

Ryan Ingram
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
Reply | Threaded
Open this post in threaded view
|

Re: Currying function using values from array

Henning Thielemann-4
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
Reply | Threaded
Open this post in threaded view
|

Re: Currying function using values from array

Sukit Tretriluxana
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:

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