help with types and composition

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

help with types and composition

Britt Anderson
I would like to write a function that takes two lists of numbers and
returns a number. For simplicity, let's assume an integer, i.e.
myfunc:: [Integer]->[Integer]->Integer
But I can't quite get things right when trying to
define myfunc = ...
 and making the arguments implicit.

My difficulty might be seen with the following two functions,
let,

f1 = (zipWith ($)) . (map  (*))

f2 = sum


if I set the types such that f1 returns [Integer] and sum accepts
[Integer] it seems that somehow I should be able to compose them in to a
single function that takes two lists and returns the number, but f1 . f2
and numerous variations don't work. I can curry some list l and f1 . (f2
l) works, but is there a way to get f1 and f2 combined into a function
that accepts two lists?


My problem is not really about writing the function but about
composition. I can write the function with arguments or a local lambda  
that suits my practical purpose. But the fact that I think I should be
able to compose f1 . f2 somehow reveals a conceptual misunderstanding
that I hope someone will help me clear up.

Thank you,
Britt Anderson
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090702/5c952c69/attachment.html
Reply | Threaded
Open this post in threaded view
|

help with types and composition

Sean Bartell
>
> f1 = (zipWith ($)) . (map  (*))
>
> f2 = sum
>

First, f1 would be clearer as zipWith (*).

Second, look at the type of (.):

(.) :: (b -> c) -> (a -> b) -> (a -> c)

Notice that (b -> c) and (a -> b) each take one argument, but f1 takes two
arguments. That's why using (.) with f1 doesn't work.

You can do what you want by uncurrying f1 so it takes only one argument,
which makes it easier to compose. You can then re-curry the result after you
do the composition.

f1 :: [Integer] -> [Integer] -> [Integer]
uncurry f1 :: ([Integer], [Integer]) -> [Integer]
f2 . uncurry f1 :: ([Integer], [Integer]) -> Integer
curry (f2 . uncurry f1) :: [Integer] -> [Integer] -> Integer

I'm sure there are shorter versions that use more than just (.), curry, and
uncurry.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090702/2955a16d/attachment.html
Reply | Threaded
Open this post in threaded view
|

Fwd: [Haskell-beginners] help with types and composition

Alexander Dunlap
In reply to this post by Britt Anderson
Oops...wrong list address...sorry


---------- Forwarded message ----------
From: Alexander Dunlap <[hidden email]>
Date: Thu, Jul 2, 2009 at 8:54 PM
Subject: Re: [Haskell-beginners] help with types and composition
To: Britt Anderson <[hidden email]>, [hidden email]


On Thu, Jul 2, 2009 at 10:54 AM, Britt Anderson<[hidden email]> wrote:

> I would like to write a function that takes two lists of numbers and returns
> a number. For simplicity, let's assume an integer, i.e.
> myfunc:: [Integer]->[Integer]->Integer
> But I can't quite get things right when trying to
> define myfunc = ...
> ?and making the arguments implicit.
>
> My difficulty might be seen with the following two functions,
> let,
>
> f1 = (zipWith ($)) . (map? (*))
>
> f2 = sum
>
>
> if I set the types such that f1 returns [Integer] and sum accepts [Integer]
> it seems that somehow I should be able to compose them in to a single
> function that takes two lists and returns the number, but f1 . f2 and
> numerous variations don't work. I can curry some list l and f1 . (f2 l)
> works, but is there a way to get f1 and f2 combined into a function that
> accepts two lists?
>
>
> My problem is not really about writing the function but about composition. I
> can write the function with arguments or a local lambda? that suits my
> practical purpose. But the fact that I think I should be able to compose f1
> . f2 somehow reveals a conceptual misunderstanding that I hope someone will
> help me clear up.
>
> Thank you,
> Britt Anderson
>
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/beginners
>
>

Try

(f2 .) . f1

. The type of (f2 .) is (a -> [Integer]) -> a -> Integer and the type
of (.) is (b -> c) -> (a -> b) -> (a -> c) so for the second (.), b ::
([Integer] -> [Integer]), c :: ([Integer] -> Integer) and a ::
[Integer] so the final type is [Integer] -> [Integer] -> Integer. (It
might be easier to work out the types yourself if you can - my
description is doubtless rather difficult to follow.)

A word of caution, though - most Haskellers in my experience prefer to
not do this type of composition; they find it clearer to specify one
or both of the arguments explicitly.

Hope that helps you,

Alex
Reply | Threaded
Open this post in threaded view
|

help with types and composition

Geoffrey Marchant
In reply to this post by Britt Anderson
I usually go with
> (f1 .) . f2

Which makes the solution for the particular example:

> sumOfProducts = (sum .) . zipWith (*)

But if you want the operator that achieves this effect for arbitrary
functions,

> ((.) (.) (.))

does the trick. Or, if SKI is your thing, you might also try

> (ap (const ap) (ap (const const) (ap (const ap) const)))

but I don't usually do it that way unless I'm feeling particularly perverse.


On Thu, Jul 2, 2009 at 11:54 AM, Britt Anderson <[hidden email]> wrote:

>  I would like to write a function that takes two lists of numbers and
> returns a number. For simplicity, let's assume an integer, i.e.
> myfunc:: [Integer]->[Integer]->Integer
> But I can't quite get things right when trying to
> define myfunc = ...
>  and making the arguments implicit.
>
> My difficulty might be seen with the following two functions,
> let,
>
> f1 = (zipWith ($)) . (map  (*))
>
> f2 = sum
>
>
> if I set the types such that f1 returns [Integer] and sum accepts [Integer]
> it seems that somehow I should be able to compose them in to a single
> function that takes two lists and returns the number, but f1 . f2 and
> numerous variations don't work. I can curry some list l and f1 . (f2 l)
> works, but is there a way to get f1 and f2 combined into a function that
> accepts two lists?
>
>
> My problem is not really about writing the function but about composition.
> I can write the function with arguments or a local lambda  that suits my
> practical purpose. But the fact that I think I should be able to compose f1
> . f2 somehow reveals a conceptual misunderstanding that I hope someone will
> help me clear up.
>
> Thank you,
> Britt Anderson
>
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090703/1b77074d/attachment.html