Re: [Haskell-cafe] Heavy lift-ing

2010-08-18 Thread Tilo Wiklund
> I think the point that was being made is that:
>
> liftM2 (flip f) /= flip (liftM2 f)
>
> This is because the former (well: liftM2 (flip f) a b)  effectively does:
>
> do {x <- a; y <- b; return (f y x)}
>
> Whereas the latter (flip (liftM2 f) a b) effectively does:
>
> do {y <- b; x <- a; return (f y x)}
>
> That is, the order of the arguments to liftM2 matters because they are
> executed in that order.  So lifting the flipped function has a different
> effect to flipping the lifted function.
>
> Thanks,
>
> Neil.

Thanks, I can see how that could lead to confusion.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-08-18 Thread Neil Brown

On 17/08/10 17:13, Tilo Wiklund wrote:

On 24/07/2010, aditya siram  wrote:
   

Perhaps I'm being unclear again. All I was trying to say was that:
liftM2 (-) [0,1] [2,3] /= liftM2 (-) [2,3] [0,1]

-deech
 

I'm sorry if I'm bumping an old thread, but why should "liftM2 f" be
commutative when "f" isn't?

(I hope I'm not responding incorrectly)
   

I think the point that was being made is that:

liftM2 (flip f) /= flip (liftM2 f)

This is because the former (well: liftM2 (flip f) a b)  effectively does:

do {x <- a; y <- b; return (f y x)}

Whereas the latter (flip (liftM2 f) a b) effectively does:

do {y <- b; x <- a; return (f y x)}

That is, the order of the arguments to liftM2 matters because they are 
executed in that order.  So lifting the flipped function has a different 
effect to flipping the lifted function.


Thanks,

Neil.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-08-17 Thread Tilo Wiklund
On 24/07/2010, aditya siram  wrote:
> Perhaps I'm being unclear again. All I was trying to say was that:
> liftM2 (-) [0,1] [2,3] /= liftM2 (-) [2,3] [0,1]
>
> -deech

I'm sorry if I'm bumping an old thread, but why should "liftM2 f" be
commutative when "f" isn't?

(I hope I'm not responding incorrectly)
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-24 Thread michael rice
Prelude Control.Monad> liftM2 (\a b -> a : b : []) "abc" "123"
["a1","a2","a3","b1","b2","b3","c1","c2","c3"]
Prelude Control.Monad> 

Got it!

Thanks to all.

Michael

--- On Sat, 7/24/10, aditya siram  wrote:

From: aditya siram 
Subject: Re: [Haskell-cafe] Heavy lift-ing
To: "Max Rabkin" 
Cc: "haskell-cafe@haskell.org" , "Lennart Augustsson" 

Date: Saturday, July 24, 2010, 10:35 AM

Perhaps I'm being unclear again. All I was trying to say was that:
liftM2 (-) [0,1] [2,3] /= liftM2 (-) [2,3] [0,1]

-deech

On Sat, Jul 24, 2010 at 9:30 AM, Max Rabkin  wrote:
> On Sat, Jul 24, 2010 at 4:08 PM, aditya siram  wrote:
>> I wouldn't-it was a bad example. My only point was that because of the
>> way (>>=) is implemented for lists the order of the arguments 'a' and
>> 'b' in 'liftM2 f a b' matters.
>>
>> -deech
>
> No, it's not. The type of liftM2 makes this clear:
>
> liftM2 :: (Monad m) => (a -> b -> r) -> m a -> m b -> m r
>
> The arguments to the function *must* come in the right order, because
> there is no way to match (a) with (m b) or (b) with (m a). Since
> liftM2 is parametrically polymorphic in (a) and (b), it can't behave
> differently in the case where (a = b).
>
> --Max
>
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe



  ___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-24 Thread aditya siram
Perhaps I'm being unclear again. All I was trying to say was that:
liftM2 (-) [0,1] [2,3] /= liftM2 (-) [2,3] [0,1]

-deech

On Sat, Jul 24, 2010 at 9:30 AM, Max Rabkin  wrote:
> On Sat, Jul 24, 2010 at 4:08 PM, aditya siram  wrote:
>> I wouldn't-it was a bad example. My only point was that because of the
>> way (>>=) is implemented for lists the order of the arguments 'a' and
>> 'b' in 'liftM2 f a b' matters.
>>
>> -deech
>
> No, it's not. The type of liftM2 makes this clear:
>
> liftM2 :: (Monad m) => (a -> b -> r) -> m a -> m b -> m r
>
> The arguments to the function *must* come in the right order, because
> there is no way to match (a) with (m b) or (b) with (m a). Since
> liftM2 is parametrically polymorphic in (a) and (b), it can't behave
> differently in the case where (a = b).
>
> --Max
>
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-24 Thread Max Rabkin
On Sat, Jul 24, 2010 at 4:08 PM, aditya siram  wrote:
> I wouldn't-it was a bad example. My only point was that because of the
> way (>>=) is implemented for lists the order of the arguments 'a' and
> 'b' in 'liftM2 f a b' matters.
>
> -deech

No, it's not. The type of liftM2 makes this clear:

liftM2 :: (Monad m) => (a -> b -> r) -> m a -> m b -> m r

The arguments to the function *must* come in the right order, because
there is no way to match (a) with (m b) or (b) with (m a). Since
liftM2 is parametrically polymorphic in (a) and (b), it can't behave
differently in the case where (a = b).

--Max
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-24 Thread aditya siram
I wouldn't-it was a bad example. My only point was that because of the
way (>>=) is implemented for lists the order of the arguments 'a' and
'b' in 'liftM2 f a b' matters.

-deech

On Sat, Jul 24, 2010 at 1:37 AM, Lennart Augustsson
 wrote:
> Why would you expect swapped operands to (-) ?
>
>
> Sent from my iPad
>
> On Jul 23, 2010, at 20:12, aditya siram  wrote:
>
>> Lists are non-deterministic, but the function taken by liftM2 does not
>> necessarily generate all possible outcomes. In the case of (+) it
>> does, not in the case of (-):
>> liftM2 (-) [0,1] [2,3] => [0-1,0-2,1-2,1-3] => [-2,-3,-1,-2]
>> if all possible cases were generated between the two lists we have to
>> include also:
>> [2-0,2-1,3-0,3-1]
>>
>> -deech
>>
>> On Fri, Jul 23, 2010 at 3:44 PM, Alex Stangl  wrote:
>>> On Fri, Jul 23, 2010 at 11:43:08AM -0700, michael rice wrote:
 What does it mean to "promote a function to a monad?"

 It would seem that the monad values must understand the function that's 
 being promoted, like Ints understand (+).

 Prelude Control.Monad> liftM2 (+) (Just 1) (Just 1)
 Just 2

 But how does one add [0,1] and [0,2] to get [0,2,1,3]?
>>>
>>> It depends upon the semantics of the particular monad. List monads
>>> represent nondeterminism. So, for example, [0,1] represents a 0 or
>>> 1, and [0,2] represents a 0 or 2.
>>>
>>> When you add 0 or 1 to 0 or 2, your possible answers are [0,2,1,3].
>>>
>>> Alex
>>> ___
>>> Haskell-Cafe mailing list
>>> Haskell-Cafe@haskell.org
>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>
>> ___
>> Haskell-Cafe mailing list
>> Haskell-Cafe@haskell.org
>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-23 Thread Alex Stangl
On Fri, Jul 23, 2010 at 09:12:44PM -0500, aditya siram wrote:
> Lists are non-deterministic, but the function taken by liftM2 does not
> necessarily generate all possible outcomes. In the case of (+) it
> does, not in the case of (-):
> liftM2 (-) [0,1] [2,3] => [0-1,0-2,1-2,1-3] => [-2,-3,-1,-2]
> if all possible cases were generated between the two lists we have to
> include also:
> [2-0,2-1,3-0,3-1]

If I have a - b where a and b are both non-deterministic, I wouldn't
expect to also include in my solution set all the results of b - a.
What if you have a / b? Would you try to include b / a, too, even
though some values of a may be zero?

Alex
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-23 Thread aditya siram
Lists are non-deterministic, but the function taken by liftM2 does not
necessarily generate all possible outcomes. In the case of (+) it
does, not in the case of (-):
liftM2 (-) [0,1] [2,3] => [0-1,0-2,1-2,1-3] => [-2,-3,-1,-2]
if all possible cases were generated between the two lists we have to
include also:
[2-0,2-1,3-0,3-1]

-deech

On Fri, Jul 23, 2010 at 3:44 PM, Alex Stangl  wrote:
> On Fri, Jul 23, 2010 at 11:43:08AM -0700, michael rice wrote:
>> What does it mean to "promote a function to a monad?"
>>
>> It would seem that the monad values must understand the function that's 
>> being promoted, like Ints understand (+).
>>
>> Prelude Control.Monad> liftM2 (+) (Just 1) (Just 1)
>> Just 2
>>
>> But how does one add [0,1] and [0,2] to get [0,2,1,3]?
>
> It depends upon the semantics of the particular monad. List monads
> represent nondeterminism. So, for example, [0,1] represents a 0 or
> 1, and [0,2] represents a 0 or 2.
>
> When you add 0 or 1 to 0 or 2, your possible answers are [0,2,1,3].
>
> Alex
> ___
> Haskell-Cafe mailing list
> Haskell-Cafe@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-23 Thread Jürgen Doser
El vie, 23-07-2010 a las 16:35 -0700, michael rice escribió:
> Thanks all,
> 
> Wild, at least up to the "optional" part, which I haven't dug into
> yet.
> 
> So the (+) for the Maybe monad and the (+) for the List monad are one
> in the same, the magic springs from the monads.
> 
> Why is it called "lift"-ing?


g :: m a -> m b -> m c
   /\
  /||\
   ||
   ||
f ::   a ->   b ->   c


liftM2 "lifts" the function f and transforms it into the function g =
liftM2 f. 

Does that picture help?

Jürgen

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-23 Thread Alexander Solla


On Jul 23, 2010, at 4:35 PM, michael rice wrote:


Why is it called "lift"-ing?


Basically, because mathematicians like enlightening metaphors.  It is  
a mathematical term.


A "monadic value" has an "underlying" value.  To turn a function that  
works on the underlying value into one that works on a monadic value,  
you have to lift it.

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-23 Thread michael rice
Thanks all,

Wild, at least up to the "optional" part, which I haven't dug into yet.

So the (+) for the Maybe monad and the (+) for the List monad are one in the 
same, the magic springs from the monads.

Why is it called "lift"-ing?

Michael


--- On Fri, 7/23/10, Jürgen Doser  wrote:

From: Jürgen Doser 
Subject: Re: [Haskell-cafe] Heavy lift-ing
To: "michael rice" 
Cc: haskell-cafe@haskell.org
Date: Friday, July 23, 2010, 4:50 PM

El vie, 23-07-2010 a las 15:05 -0400, Nick Bowler escribió:
> On 11:43 Fri 23 Jul     , michael rice wrote:
> [...]
> > But how does one add [0,1] and [0,2] to get [0,2,1,3]?
> 
>
 liftM2 (+) [0,1] [0,2] gives the list
> 
>   [0+0, 0+2, 1+0, 1+2]

which one could have found out by asking ghci:

Prelude Control.Monad> let f a b = show a ++ " + " ++ show b
Prelude Control.Monad> liftM2 f [0,1] [0,2]
["0 + 0","0 + 2","1 + 0","1 + 2"]

or simpler:

Prelude Control.Monad> liftM2 (,) [0,1] [2,3]
[(0,2),(0,3),(1,2),(1,3)]

i.e., the in the list monad, you pair each element of one list with each
element of the other(s).

> (recall that (>>=) in the list monad is concatMap).

(>>=) = flip concatMap, to be precise. Or, concatMap = (=<<)

Now let's have some fun with equational reasoning to see what liftM2
does exactly: (Only read this if you really want to!)

liftM2 f a b 

    = { definition of liftM2 }

do {x <- a; y <- b; return (f x y)}

    = { simplified translation
 of do-notation }

a >>= \x -> (b >>= \y -> return (f x y))

    = { change (>>=) to (=<<) and flip arguments }

(\x -> ((\y -> return (f x y)) =<< b)) =<< a 

    = { specialized to the list monad }

(\x -> ((\y -> [f x y])) `concatMap` b)) `concatMap` a 

    = { change concatMap to prefix application }

concatMap (\x -> concatMap (\y -> [x+y]) b) a

and indeed:

Prelude> concatMap (\x -> concatMap (\y -> [x+y]) [0,2]) [0,1]
[0,2,1,3]

with some effort, I think one can understand what happens here. It
should also be clear how this is generalized to liftM3, liftM4, etc. 

Oh, btw, what about liftM1? Obviously, this should be the following:

liftM1 f a

    = { definition }

do { x <- a ; return f a }
  
    = { same changes as above
 }

concatMap (\x -> [f x]) a

    = { definition of concatMap }

concat (map (\x -> [f x]) a

    = { concating singletons can be simplified } 

map (\x -> f x) a

    = { eta-reduction }

map f a

i.e., liftM1 = map, which is indeed just fmap for lists, as already
pointed out.

You can use this to simplify the last line of the concatMap derivation
above:

concatMap (\x -> concatMap (\y -> [x+y]) b) a

    = { see above }

concatMap (\x -> map (\y -> x+y) b) a

    = { use operator section }

concatMap (\x -> map (x+) b) a

which is about as clear as possible a definition for liftM2 (+)


    Jürgen






  ___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-23 Thread Jürgen Doser
El vie, 23-07-2010 a las 15:05 -0400, Nick Bowler escribió:
> On 11:43 Fri 23 Jul , michael rice wrote:
> [...]
> > But how does one add [0,1] and [0,2] to get [0,2,1,3]?
> 
> liftM2 (+) [0,1] [0,2] gives the list
> 
>   [0+0, 0+2, 1+0, 1+2]

which one could have found out by asking ghci:

Prelude Control.Monad> let f a b = show a ++ " + " ++ show b
Prelude Control.Monad> liftM2 f [0,1] [0,2]
["0 + 0","0 + 2","1 + 0","1 + 2"]

or simpler:

Prelude Control.Monad> liftM2 (,) [0,1] [2,3]
[(0,2),(0,3),(1,2),(1,3)]

i.e., the in the list monad, you pair each element of one list with each
element of the other(s).

> (recall that (>>=) in the list monad is concatMap).

(>>=) = flip concatMap, to be precise. Or, concatMap = (=<<)

Now let's have some fun with equational reasoning to see what liftM2
does exactly: (Only read this if you really want to!)

liftM2 f a b 

= { definition of liftM2 }

do {x <- a; y <- b; return (f x y)}

= { simplified translation of do-notation }

a >>= \x -> (b >>= \y -> return (f x y))

= { change (>>=) to (=<<) and flip arguments }

(\x -> ((\y -> return (f x y)) =<< b)) =<< a 

= { specialized to the list monad }

(\x -> ((\y -> [f x y])) `concatMap` b)) `concatMap` a 

= { change concatMap to prefix application }

concatMap (\x -> concatMap (\y -> [x+y]) b) a

and indeed:

Prelude> concatMap (\x -> concatMap (\y -> [x+y]) [0,2]) [0,1]
[0,2,1,3]

with some effort, I think one can understand what happens here. It
should also be clear how this is generalized to liftM3, liftM4, etc. 

Oh, btw, what about liftM1? Obviously, this should be the following:

liftM1 f a

= { definition }

do { x <- a ; return f a }
  
= { same changes as above }

concatMap (\x -> [f x]) a

= { definition of concatMap }

concat (map (\x -> [f x]) a

= { concating singletons can be simplified } 

map (\x -> f x) a

= { eta-reduction }

map f a

i.e., liftM1 = map, which is indeed just fmap for lists, as already
pointed out.

You can use this to simplify the last line of the concatMap derivation
above:

concatMap (\x -> concatMap (\y -> [x+y]) b) a

= { see above }

concatMap (\x -> map (\y -> x+y) b) a

= { use operator section }

concatMap (\x -> map (x+) b) a

which is about as clear as possible a definition for liftM2 (+)


Jürgen



___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-23 Thread Alex Stangl
On Fri, Jul 23, 2010 at 11:43:08AM -0700, michael rice wrote:
> What does it mean to "promote a function to a monad?"
> 
> It would seem that the monad values must understand the function that's being 
> promoted, like Ints understand (+).
> 
> Prelude Control.Monad> liftM2 (+) (Just 1) (Just 1)
> Just 2
> 
> But how does one add [0,1] and [0,2] to get [0,2,1,3]?

It depends upon the semantics of the particular monad. List monads
represent nondeterminism. So, for example, [0,1] represents a 0 or
1, and [0,2] represents a 0 or 2.

When you add 0 or 1 to 0 or 2, your possible answers are [0,2,1,3].

Alex
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-23 Thread Nick Bowler
On 11:43 Fri 23 Jul , michael rice wrote:
> Hi,
> 
> I don't understand what's taking place here.
> 
> >From Hoogle:
> 
> =
> 
> liftM2 :: Monad  m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
> 
> Promote a function to a monad, scanning the monadic arguments from left to 
> right. For example,
> 
>     liftM2 (+) [0,1] [0,2] = [0,2,1,3]
>     liftM2 (+) (Just 1) Nothing = Nothing
> 
> =
> 
> What does it mean to "promote a function to a monad?"

Consider fmap, which 'promotes a function to a functor':

  fmap :: Functor f => (a -> b) -> f a -> f b

This might be easier to understand if you fully parenthesise this:

  fmap :: Functor f => (a -> b) -> (f a -> f b)

In other words, fmap takes a function on ordinary values as input, and
outputs a function on a particular Functor.

Now consider liftM, which 'promotes a function to a monad':

  liftM :: Monad m => (a -> b) -> m a -> m b

Hey, this looks almost the same as fmap (it is)!  Now, monads have
additional structure which allows us to promote more complicated
functions, for example:

  liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c

which, when fully parenthesised, looks like

  liftM2 :: Monad m => (a -> b -> c) -> (m a -> m b -> m c)

What we have now is that we can promote a 'two argument' function to
Monads (this is not possible on mere Functors, hence there's no fmap2).

> It would seem that the monad values must understand the function
> that's being promoted, like Ints understand (+).

Yes, liftM2 (+) gives you a new function with type
 
  (Num a, Monad m) => m a -> m a -> m a

> But how does one add [0,1] and [0,2] to get [0,2,1,3]?

liftM2 (+) [0,1] [0,2] gives the list

  [0+0, 0+2, 1+0, 1+2]

(recall that (>>=) in the list monad is concatMap).

-- 
Nick Bowler, Elliptic Technologies (http://www.elliptictech.com/)
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Heavy lift-ing

2010-07-23 Thread Albert Y. C. Lai

On 10-07-23 02:43 PM, michael rice wrote:

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r

[...]

What does it mean to "promote a function to a monad?"


liftM2 f m1 m2 is canned code for

do
  a1 <- m1
  a2 <- m2
  return (f a1 a2)

for example liftM2 f [s,t] [x,y] is [f s x, f s y, f t x, f t y]

liftM2 (++) getLine getLine reads two lines and concatenates them.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


[Haskell-cafe] Heavy lift-ing

2010-07-23 Thread michael rice
Hi,

I don't understand what's taking place here.

>From Hoogle:

=

liftM2 :: Monad  m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r

Promote a function to a monad, scanning the monadic arguments from left to 
right. For example,

    liftM2 (+) [0,1] [0,2] = [0,2,1,3]
    liftM2 (+) (Just 1) Nothing = Nothing

=

What does it mean to "promote a function to a monad?"

It would seem that the monad values must understand the function that's being 
promoted, like Ints understand (+).

Prelude Control.Monad> liftM2 (+) (Just 1) (Just 1)
Just 2

But how does one add [0,1] and [0,2] to get [0,2,1,3]?

Michael 



  ___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe