# Currying function using values from array Classic List Threaded 8 messages Open this post in threaded view
|

## Currying function using values from array

Open this post in threaded view
|

## Re: Currying function using values from array

Open this post in threaded view
|

## Re: Currying function using values from array

Open this post in threaded view
|

## Re: Currying function using values from array

Open this post in threaded view
|

## Re: Currying function using values from array

Open this post in threaded view
|

## Re: Currying function using values from array

 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