Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-07-05 Thread Facundo Domínguez
 That precedent supports the view that e.g. a command-line flag
 shouldn't affect behavior without the type reflecting it, e.g. by
 doing IO, but the de facto use of the unsafe IO trick means not
 everyone agrees.

For those interested, here's [1] a case where treating command line
arguments as top level constants went wrong.
Look specifically at the section named Crime Doesn't Pay.

Best,
Facundo

[1] http://www.aosabook.org/en/ghc.html


 Date: Tue, 3 Jul 2012 17:49:48 -0400
 From: Alvaro Gutierrez radi...@google.com
 Subject: Re: [Haskell-cafe] Martin Odersky on What's wrong with
 Monads
 To: Dominique Devriese dominique.devri...@cs.kuleuven.be
 Cc: haskell-cafe@haskell.org
 Message-ID:
 cac6k+tpuidrtac_ccfa9ewawdpg1adaht96rgmc_s5wtvjw...@mail.gmail.com
 Content-Type: text/plain; charset=ISO-8859-1

 On Thu, Jun 28, 2012 at 2:53 PM, Dominique Devriese
 dominique.devri...@cs.kuleuven.be wrote:
 2012/6/27 Tillmann Rendel ren...@informatik.uni-marburg.de:
 How would you implement this requirement in Haskell without changing the
 line amount (Leaf x) = x?

 I may be missing the point here, but having worked on large code bases
 with a wide variety contributors before, I find it very advantageous
 that programmers are prevented from writing an amount function whose
 behaviour depends on command line arguments without at least an
 indication in the type. The fact that the function can not perform
 stuff like that is precisely the guarantee that the Haskell type gives
 me...

 I don't think there's an answer that's uniformly right; it depends on
 whether you think of the input to the program, e.g. the environment,
 command-line arguments, etc. as 'constant' and in some sense, pure.
 The latter are constant in the sense that they never change, but they
 are not fixed at compile-time. Other languages effectively treat them
 as pure (by passing them directly to main), whereas Haskell chooses
 not to, which is probably the reason why getArgs has IO in its type
 (something that seems unintuitive at first.)

 That precedent supports the view that e.g. a command-line flag
 shouldn't affect behavior without the type reflecting it, e.g. by
 doing IO, but the de facto use of the unsafe IO trick means not
 everyone agrees.


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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-07-05 Thread Tom Murphy
In practice, the amount of time you have to spend testing each function, to
make sure its IO doesn't trip up in some corner case, is usually greater
than the amount of time a rewrite-for-IO would take.

Tom
On Jun 28, 2012 2:54 PM, Dominique Devriese 
dominique.devri...@cs.kuleuven.be wrote:

 2012/6/27 Tillmann Rendel ren...@informatik.uni-marburg.de:
  MightyByte wrote:
 
  Of course every line of your program that uses a Foo will change if you
  switch
  to IO Foo instead.
 
 
  But we often have to also change lines that don't use Foo at all. For
  example, here is the type of binary trees of integers:
 
   data Tree = Leaf Integer | Branch (Tree Integer) (Tree Integer)
 
  A function to add up all integers in a tree:
 
   amount:: Tree - Integer
   amount (Leaf x) = x
   amount (Branch t1 t2) = amountt1 + amountt2
 
  All fine so far. Now, consider the following additional requirement: If
 the
  command-line flag --multiply is set, the function amount computes the
  product instead of the sum.
 
  In a language with implicit side effects, it is easy to implement this.
 We
  just change the third line of the amount function to check whether to
 call
  (+) or (*). In particular, we would not touch the other two lines.
 
  How would you implement this requirement in Haskell without changing the
  line amount (Leaf x) = x?

 I may be missing the point here, but having worked on large code bases
 with a wide variety contributors before, I find it very advantageous
 that programmers are prevented from writing an amount function whose
 behaviour depends on command line arguments without at least an
 indication in the type. The fact that the function can not perform
 stuff like that is precisely the guarantee that the Haskell type gives
 me...

 Dominique

 ___
 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] Martin Odersky on What's wrong with Monads

2012-07-03 Thread Alvaro Gutierrez
On Tue, Jun 26, 2012 at 6:19 PM, Tillmann Rendel
ren...@informatik.uni-marburg.de wrote:
 How would you implement this requirement in Haskell without changing the
 line amount (Leaf x) = x?

The hflags library [http://hackage.haskell.org/package/hflags] seems
to do that, however...

 (I actually see three ways of doing this in Haskell, but all have serious
 drawbacks and do not fully solve the problem).

...it uses the unsafe IO trick
[http://www.haskell.org/haskellwiki/Top_level_mutable_state], which
may be one of those three ways you aren't fond of.

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-07-03 Thread Alvaro Gutierrez
On Thu, Jun 28, 2012 at 2:53 PM, Dominique Devriese
dominique.devri...@cs.kuleuven.be wrote:
 2012/6/27 Tillmann Rendel ren...@informatik.uni-marburg.de:
 How would you implement this requirement in Haskell without changing the
 line amount (Leaf x) = x?

 I may be missing the point here, but having worked on large code bases
 with a wide variety contributors before, I find it very advantageous
 that programmers are prevented from writing an amount function whose
 behaviour depends on command line arguments without at least an
 indication in the type. The fact that the function can not perform
 stuff like that is precisely the guarantee that the Haskell type gives
 me...

I don't think there's an answer that's uniformly right; it depends on
whether you think of the input to the program, e.g. the environment,
command-line arguments, etc. as 'constant' and in some sense, pure.
The latter are constant in the sense that they never change, but they
are not fixed at compile-time. Other languages effectively treat them
as pure (by passing them directly to main), whereas Haskell chooses
not to, which is probably the reason why getArgs has IO in its type
(something that seems unintuitive at first.)

That precedent supports the view that e.g. a command-line flag
shouldn't affect behavior without the type reflecting it, e.g. by
doing IO, but the de facto use of the unsafe IO trick means not
everyone agrees.

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-28 Thread Alberto G. Corona
The problem of monads is that it defines different execution models,
 besides the funcional,/lazy/declarative mode. There is no such problem in
imperative languages, which work ever in an hardwired IO monad. But this
means that the programmer has to code  the extra behaviour needed in each
application  to do the same.

I summarized this here:
http://haskell-web.blogspot.com.es/2012/06/intuitive-explanation-of-algorithms-in.html


It pretend to be intuitive, not accurate. (See disclaimer ;)  . Comments
welcome

2012/6/27 Yves Parès yves.pa...@gmail.com

  I'm not happy with any of these options.

 Why are you unhappy with the ImplicitParams option?

 It's pretty much like resorting to a newtype, as it's been suggested
 before.


 2012/6/27 Tillmann Rendel ren...@informatik.uni-marburg.de

 Hi Rico,

 Rico Moorman wrote:

  data Tree = Leaf Integer | Branch (Tree Integer) (Tree Integer)

  amount:: Tree - Integer
  amount (Leaf x) = x
  amount (Branch t1 t2) = amountt1 + amountt2

 [...] additional requirement: If the command-line flag --multiply is
 set,

 the function amount computes the product instead of the sum.

 How would you implement this requirement in Haskell without changing the
 line amount (Leaf x) = x?


  The (for me at least) most obvious way to do this would be, to make the
 operation to be applied to determine the amount (+ or *) an explicit
 parameter in the function's definition.


  data Tree a = Leaf a
  | Branch (Tree a) (Tree a)
  amount :: (a - a - a) - Tree a - a
  amount fun (Leaf x) = x
  amount fun (Branch t1 t2) = amount fun t1 `fun` amount fun t2


 I agree: This is the most obvious way, and also a very good way. I would
 probably do it like this.

  Which drawbacks do you see besides increased verbosity?


 Well, you did change the equation amount (Leaf x) = x to amount fun
 (Leaf x) = x. In a larger example, this means that you need to change many
 lines of many functions, just to get the the value of fun from the point
 where it is known to the point where you need it.

  [...] I am wondering which ways of doing this in Haskell you mean.


 I thought of the following three options, but see also Nathan Howells
 email for another alternative (that is related to my option (1) below):


 (1) Implicit parameters:

 {-# LANGUAGE ImplicitParams #-}
 data Tree = Leaf Integer | Branch Tree Tree

 amount :: (?fun :: Integer - Integer - Integer) = Tree - Integer

 amount (Leaf x) = x
 amount (Branch t1 t2) = ?fun (amount t1) (amount t2)


 (2) Lexical Scoping:

 data Tree = Leaf Integer | Branch Tree Tree

 amount :: (Integer - Integer - Integer) - Tree - Integer
 amount fun = amount where {

 amount (Leaf x) = x
 ; amount (Branch t1 t2) = fun (amount t1) (amount t2) }


 (3) UnsafePerformIO:

 import System.IO.Unsafe (unsafePerformIO)

 data Tree = Leaf Integer | Branch Tree Tree


 amount :: Tree - Integer
 amount (Leaf x) = x
 amount (Branch t1 t2) = fun (amount t1) (amount t2)
  where fun = unsafePerformIO ...


 I'm not happy with any of these options. Personally, I would probably go
 ahead and transform the whole program just to get the value of fun to where
 it is needed. Nevertheless, having actually done this before, I understand
 why Martin Odersky doesn't like doing it :)


  Tillmann

 __**_
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/**mailman/listinfo/haskell-cafehttp://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] Martin Odersky on What's wrong with Monads

2012-06-28 Thread MightyByte
Tillmann Rendel rendel at informatik.uni-marburg.de writes:

 
  Which drawbacks do you see besides increased verbosity?
 
 Well, you did change the equation amount (Leaf x) = x to amount fun 
 (Leaf x) = x. In a larger example, this means that you need to change 
 many lines of many functions, just to get the the value of fun from the 
 point where it is known to the point where you need it.

I would argue that no matter how good one's language is, there will always 
exist 
realistic refactorings that require you to make sweeping changes to a large 
portion of your code base.  

  [...] I am wondering which ways of doing this in Haskell you mean.
 
 I thought of the following three options, but see also Nathan Howells 
 email for another alternative (that is related to my option (1) below):
 
 (1) Implicit parameters:
snip
 (2) Lexical Scoping:
snip
 (3) UnsafePerformIO:
snip
 I'm not happy with any of these options. Personally, I would probably go 
 ahead and transform the whole program just to get the value of fun to 
 where it is needed. Nevertheless, having actually done this before, I 
 understand why Martin Odersky doesn't like doing it :)

I think that Martin's statement is an unavoidable fact of life that follows 
directly from the definition of purity and the mechanics of data dependencies.  
Of course nobody likes making sweeping changes to their app because they didn't 
anticipate the way the future would evolve.  But lets not blame monads for what 
is really a much more fundamental phenomenon.





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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-28 Thread Donn Cave
To be fair, while it's great that Functor et al. are available to
help solve problems like that with a Tree data structure, in the
present context it mostly shows that a trivial example was used
to illustrate the problem.  Unless I'm missing how this generic
fold functionality solves the more general problem.

Quoth Alberto G. Corona,

 ... There is no such problem in imperative languages, which work
 ever in an hardwired IO monad.

Or to look at it from the other direction, the problem with Haskell
is that it allows the programmer to write non-IO functions.  To the
extent that's a real problem, the solution would obviously be to
exercise some restraint with the pure code and write more in the
IO monad.  If you will humor me, we understand that this code is
equally satisfactory from a mathematical perspective and there's
no crime in it.  But does it help with the `flags problem?'

Suppose that functions f and g both have IO types;  f calls g,
and g has optional behavior depending on some IO value computed
previously, the flag.  The way I understand it, I can accomplish
this without passing the flag around:  with an IORef.

What's less clear to me is whether Haskell really supports the module
level accessible IORef value I need.  Also known as top level mutable
state.  Is the NOINLINE pragma I've been using with GHC, really a
sound and reliable practice that we're reasonably confident will be
supported by other compilers?

It feels to me like I'm pulling a weird trick, to do something that's
trivial in other programming languages.  Maybe that's part of the
problem, that imperative programming receives something a little short
of full support in Haskell, inasmuch as basic features like top level
mutable state require relatively arcane incantations.

Donn

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-28 Thread Dominique Devriese
2012/6/27 Tillmann Rendel ren...@informatik.uni-marburg.de:
 MightyByte wrote:

 Of course every line of your program that uses a Foo will change if you
 switch
 to IO Foo instead.


 But we often have to also change lines that don't use Foo at all. For
 example, here is the type of binary trees of integers:

  data Tree = Leaf Integer | Branch (Tree Integer) (Tree Integer)

 A function to add up all integers in a tree:

  amount:: Tree - Integer
  amount (Leaf x) = x
  amount (Branch t1 t2) = amountt1 + amountt2

 All fine so far. Now, consider the following additional requirement: If the
 command-line flag --multiply is set, the function amount computes the
 product instead of the sum.

 In a language with implicit side effects, it is easy to implement this. We
 just change the third line of the amount function to check whether to call
 (+) or (*). In particular, we would not touch the other two lines.

 How would you implement this requirement in Haskell without changing the
 line amount (Leaf x) = x?

I may be missing the point here, but having worked on large code bases
with a wide variety contributors before, I find it very advantageous
that programmers are prevented from writing an amount function whose
behaviour depends on command line arguments without at least an
indication in the type. The fact that the function can not perform
stuff like that is precisely the guarantee that the Haskell type gives
me...

Dominique

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-28 Thread damodar kulkarni
Any idea whether Martin Odersky has read this discussion?

Thanks and regards,
-Damodar Kulkarni


On Fri, Jun 29, 2012 at 12:23 AM, Dominique Devriese 
dominique.devri...@cs.kuleuven.be wrote:

 2012/6/27 Tillmann Rendel ren...@informatik.uni-marburg.de:
  MightyByte wrote:
 
  Of course every line of your program that uses a Foo will change if you
  switch
  to IO Foo instead.
 
 
  But we often have to also change lines that don't use Foo at all. For
  example, here is the type of binary trees of integers:
 
   data Tree = Leaf Integer | Branch (Tree Integer) (Tree Integer)
 
  A function to add up all integers in a tree:
 
   amount:: Tree - Integer
   amount (Leaf x) = x
   amount (Branch t1 t2) = amountt1 + amountt2
 
  All fine so far. Now, consider the following additional requirement: If
 the
  command-line flag --multiply is set, the function amount computes the
  product instead of the sum.
 
  In a language with implicit side effects, it is easy to implement this.
 We
  just change the third line of the amount function to check whether to
 call
  (+) or (*). In particular, we would not touch the other two lines.
 
  How would you implement this requirement in Haskell without changing the
  line amount (Leaf x) = x?

 I may be missing the point here, but having worked on large code bases
 with a wide variety contributors before, I find it very advantageous
 that programmers are prevented from writing an amount function whose
 behaviour depends on command line arguments without at least an
 indication in the type. The fact that the function can not perform
 stuff like that is precisely the guarantee that the Haskell type gives
 me...

 Dominique

 ___
 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] Martin Odersky on What's wrong with Monads

2012-06-27 Thread Tillmann Rendel

Hi Rico,

Rico Moorman wrote:

  data Tree = Leaf Integer | Branch (Tree Integer) (Tree Integer)

  amount:: Tree - Integer
  amount (Leaf x) = x
  amount (Branch t1 t2) = amountt1 + amountt2

[...] additional requirement: If the command-line flag --multiply is set,
the function amount computes the product instead of the sum.

How would you implement this requirement in Haskell without changing the
line amount (Leaf x) = x?



The (for me at least) most obvious way to do this would be, to make the
operation to be applied to determine the amount (+ or *) an explicit
parameter in the function's definition.

  data Tree a = Leaf a
  | Branch (Tree a) (Tree a)
  amount :: (a - a - a) - Tree a - a
  amount fun (Leaf x) = x
  amount fun (Branch t1 t2) = amount fun t1 `fun` amount fun t2


I agree: This is the most obvious way, and also a very good way. I would 
probably do it like this.



Which drawbacks do you see besides increased verbosity?


Well, you did change the equation amount (Leaf x) = x to amount fun 
(Leaf x) = x. In a larger example, this means that you need to change 
many lines of many functions, just to get the the value of fun from the 
point where it is known to the point where you need it.



[...] I am wondering which ways of doing this in Haskell you mean.


I thought of the following three options, but see also Nathan Howells 
email for another alternative (that is related to my option (1) below):



(1) Implicit parameters:

{-# LANGUAGE ImplicitParams #-}
data Tree = Leaf Integer | Branch Tree Tree

amount :: (?fun :: Integer - Integer - Integer) = Tree - Integer
amount (Leaf x) = x
amount (Branch t1 t2) = ?fun (amount t1) (amount t2)


(2) Lexical Scoping:

data Tree = Leaf Integer | Branch Tree Tree

amount :: (Integer - Integer - Integer) - Tree - Integer
amount fun = amount where {
amount (Leaf x) = x
; amount (Branch t1 t2) = fun (amount t1) (amount t2) }


(3) UnsafePerformIO:

import System.IO.Unsafe (unsafePerformIO)

data Tree = Leaf Integer | Branch Tree Tree

amount :: Tree - Integer
amount (Leaf x) = x
amount (Branch t1 t2) = fun (amount t1) (amount t2)
  where fun = unsafePerformIO ...


I'm not happy with any of these options. Personally, I would probably go 
ahead and transform the whole program just to get the value of fun to 
where it is needed. Nevertheless, having actually done this before, I 
understand why Martin Odersky doesn't like doing it :)


  Tillmann

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-27 Thread Yves Parès
 I'm not happy with any of these options.

Why are you unhappy with the ImplicitParams option?

It's pretty much like resorting to a newtype, as it's been suggested before.

2012/6/27 Tillmann Rendel ren...@informatik.uni-marburg.de

 Hi Rico,

 Rico Moorman wrote:

  data Tree = Leaf Integer | Branch (Tree Integer) (Tree Integer)

  amount:: Tree - Integer
  amount (Leaf x) = x
  amount (Branch t1 t2) = amountt1 + amountt2

 [...] additional requirement: If the command-line flag --multiply is
 set,

 the function amount computes the product instead of the sum.

 How would you implement this requirement in Haskell without changing the
 line amount (Leaf x) = x?


  The (for me at least) most obvious way to do this would be, to make the
 operation to be applied to determine the amount (+ or *) an explicit
 parameter in the function's definition.


  data Tree a = Leaf a
  | Branch (Tree a) (Tree a)
  amount :: (a - a - a) - Tree a - a
  amount fun (Leaf x) = x
  amount fun (Branch t1 t2) = amount fun t1 `fun` amount fun t2


 I agree: This is the most obvious way, and also a very good way. I would
 probably do it like this.

  Which drawbacks do you see besides increased verbosity?


 Well, you did change the equation amount (Leaf x) = x to amount fun
 (Leaf x) = x. In a larger example, this means that you need to change many
 lines of many functions, just to get the the value of fun from the point
 where it is known to the point where you need it.

  [...] I am wondering which ways of doing this in Haskell you mean.


 I thought of the following three options, but see also Nathan Howells
 email for another alternative (that is related to my option (1) below):


 (1) Implicit parameters:

 {-# LANGUAGE ImplicitParams #-}
 data Tree = Leaf Integer | Branch Tree Tree

 amount :: (?fun :: Integer - Integer - Integer) = Tree - Integer

 amount (Leaf x) = x
 amount (Branch t1 t2) = ?fun (amount t1) (amount t2)


 (2) Lexical Scoping:

 data Tree = Leaf Integer | Branch Tree Tree

 amount :: (Integer - Integer - Integer) - Tree - Integer
 amount fun = amount where {

 amount (Leaf x) = x
 ; amount (Branch t1 t2) = fun (amount t1) (amount t2) }


 (3) UnsafePerformIO:

 import System.IO.Unsafe (unsafePerformIO)

 data Tree = Leaf Integer | Branch Tree Tree


 amount :: Tree - Integer
 amount (Leaf x) = x
 amount (Branch t1 t2) = fun (amount t1) (amount t2)
  where fun = unsafePerformIO ...


 I'm not happy with any of these options. Personally, I would probably go
 ahead and transform the whole program just to get the value of fun to where
 it is needed. Nevertheless, having actually done this before, I understand
 why Martin Odersky doesn't like doing it :)


  Tillmann

 __**_
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/**mailman/listinfo/haskell-cafehttp://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] Martin Odersky on What's wrong with Monads

2012-06-26 Thread Tillmann Rendel

Hi,

MightyByte wrote:

Of course every line of your program that uses a Foo will change if you switch
to IO Foo instead.


But we often have to also change lines that don't use Foo at all. For 
example, here is the type of binary trees of integers:


  data Tree = Leaf Integer | Branch (Tree Integer) (Tree Integer)

A function to add up all integers in a tree:

  amount:: Tree - Integer
  amount (Leaf x) = x
  amount (Branch t1 t2) = amountt1 + amountt2

All fine so far. Now, consider the following additional requirement: If 
the command-line flag --multiply is set, the function amount computes 
the product instead of the sum.


In a language with implicit side effects, it is easy to implement this. 
We just change the third line of the amount function to check whether to 
call (+) or (*). In particular, we would not touch the other two lines.


How would you implement this requirement in Haskell without changing the 
line amount (Leaf x) = x?


(I actually see three ways of doing this in Haskell, but all have 
serious drawbacks and do not fully solve the problem).


Here it seems not so bad just to change all three lines of the amount 
function, even if they are not strictly related to the semantic change 
we want to make. But in a real program, this situation can translate to 
changing thousands of lines of code in many functions just to implement 
a minor change to a single requirement.


  Tillmann

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-26 Thread Ozgun Ataman
We could debate this endlessly (as is common), but I would argue that a clean 
design would make the option and alternative of multiplying explicit in its 
design instead of including calls to fetch command line arguments in an ad-hoc 
fashion everywhere. 

The Haskell way of encoding this would be to define an app configuration data 
type (say AppConfig), parse the command line arguments into it upfront in IO 
and then run your application either in a in a monad that's an instance of 
(MonadReader MyConfig) or explicitly pass the option in where needed by a 
function. If you've designed your application this way, adding a new command 
line option would cause very little -if any- refactoring. If not, in my 
experience it is usually a 30 minute intense refactoring campaign.

I suspect there might be a way to use implicit arguments here as well, but 
that's something I've never felt compelled to use.

This kind of separation of concerns and pure application design is one of the 
things that (I think) many people really like about Haskell.

Cheers,
Oz


On Tuesday, June 26, 2012 at 6:19 PM, Tillmann Rendel wrote:

 Hi,
 
 MightyByte wrote:
  Of course every line of your program that uses a Foo will change if you 
  switch
  to IO Foo instead.
  
 
 
 But we often have to also change lines that don't use Foo at all. For 
 example, here is the type of binary trees of integers:
 
 data Tree = Leaf Integer | Branch (Tree Integer) (Tree Integer)
 
 A function to add up all integers in a tree:
 
 amount:: Tree - Integer
 amount (Leaf x) = x
 amount (Branch t1 t2) = amountt1 + amountt2
 
 All fine so far. Now, consider the following additional requirement: If 
 the command-line flag --multiply is set, the function amount computes 
 the product instead of the sum.
 
 In a language with implicit side effects, it is easy to implement this. 
 We just change the third line of the amount function to check whether to 
 call (+) or (*). In particular, we would not touch the other two lines.
 
 How would you implement this requirement in Haskell without changing the 
 line amount (Leaf x) = x?
 
 (I actually see three ways of doing this in Haskell, but all have 
 serious drawbacks and do not fully solve the problem).
 
 Here it seems not so bad just to change all three lines of the amount 
 function, even if they are not strictly related to the semantic change 
 we want to make. But in a real program, this situation can translate to 
 changing thousands of lines of code in many functions just to implement 
 a minor change to a single requirement.
 
 Tillmann
 
 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org (mailto: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] Martin Odersky on What's wrong with Monads

2012-06-26 Thread Patrick Hurst
I'd also say that reading command-line flags inside a simple function like
amount is a pretty large code smell. The only case in which it isn't would
be when the codebase is so small that redesigning the Haskell to be in IO
(or switch between amountPlus and amountTimes) is negligible anyway.

On Jun 26, 2012, at 18:59, Ozgun Ataman ozata...@gmail.com wrote:

We could debate this endlessly (as is common), but I would argue that a
clean design would make the option and alternative of multiplying
explicit in its design instead of including calls to fetch command line
arguments in an ad-hoc fashion everywhere.

The Haskell way of encoding this would be to define an app configuration
data type (say AppConfig), parse the command line arguments into it upfront
in IO and then run your application either in a in a monad that's an
instance of (MonadReader MyConfig) or explicitly pass the option in where
needed by a function. If you've designed your application this way, adding
a new command line option would cause very little -if any- refactoring. If
not, in my experience it is usually a 30 minute intense refactoring
campaign.

I suspect there might be a way to use implicit arguments here as well, but
that's something I've never felt compelled to use.

This kind of separation of concerns and pure application design is one of
the things that (I think) many people really like about Haskell.

Cheers,
Oz

On Tuesday, June 26, 2012 at 6:19 PM, Tillmann Rendel wrote:

Hi,

MightyByte wrote:

Of course every line of your program that uses a Foo will change if you
switch
to IO Foo instead.


But we often have to also change lines that don't use Foo at all. For
example, here is the type of binary trees of integers:

data Tree = Leaf Integer | Branch (Tree Integer) (Tree Integer)

A function to add up all integers in a tree:

amount:: Tree - Integer
amount (Leaf x) = x
amount (Branch t1 t2) = amountt1 + amountt2

All fine so far. Now, consider the following additional requirement: If
the command-line flag --multiply is set, the function amount computes
the product instead of the sum.

In a language with implicit side effects, it is easy to implement this.
We just change the third line of the amount function to check whether to
call (+) or (*). In particular, we would not touch the other two lines.

How would you implement this requirement in Haskell without changing the
line amount (Leaf x) = x?

(I actually see three ways of doing this in Haskell, but all have
serious drawbacks and do not fully solve the problem).

Here it seems not so bad just to change all three lines of the amount
function, even if they are not strictly related to the semantic change
we want to make. But in a real program, this situation can translate to
changing thousands of lines of code in many functions just to implement
a minor change to a single requirement.

Tillmann

___
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] Martin Odersky on What's wrong with Monads

2012-06-26 Thread Nathan Howell
On Tue, Jun 26, 2012 at 3:19 PM, Tillmann Rendel
ren...@informatik.uni-marburg.de wrote:
 A function to add up all integers in a tree:

  amount:: Tree - Integer
  amount (Leaf x) = x
  amount (Branch t1 t2) = amountt1 + amountt2

 All fine so far. Now, consider the following additional requirement: If the
 command-line flag --multiply is set, the function amount computes the
 product instead of the sum.

 How would you implement this requirement in Haskell without changing the
 line amount (Leaf x) = x?

One option is to encode the desired behavior at the type level. By
extended the data type slightly and adding a Functor instance,
selecting between a product and a sum can be done using their Monoid
newtypes:

import Data.Monoid
import System.Environment

data Tree a = Leaf a | Branch (Tree a) (Tree a)

instance Functor Tree where
  f `fmap` Leaf x = Leaf (f x)
  f `fmap` Branch x y = Branch (fmap f x) (fmap f y)

amount :: Monoid a = Tree a - a
amount (Leaf x) = x
amount (Branch t1 t2) = amount t1  amount t2

main :: IO ()
main = do
  args - getArgs

  let val :: Tree Int
  val = Branch (Leaf 8) (Leaf 18)

  let getResult :: Tree Int - Int
  getResult = case args of
[--multiply] - getProduct . amount . fmap Product
_  - getSum . amount . fmap Sum

  print . getResult $ val

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-25 Thread Chris Dornan
On 24 June 2012 18:46, Alexander Solla alex.so...@gmail.com wrote:


 I sort of see where you're coming from.  But I'm having a hard time seeing
 how this complaint would work with respect to Maybe and the other pure
 monads.  In other words, I suspect the problem you're describing is
 particular to IO and IO-like monads.


Yes this problem is specific to IO-based functions. If you didn't know
anything about monads yet would have written a Maybe/Either function then
the types are identical to the monadic formulation, and the monadic
framework in this case is just helping you to structure everything. Unless
this structucture is obscuring or confusing matters (and I don't see it)
its difficult to imagine any objection here.


 I don't know SML.  How is our list monadic and theirs not?  In
 particular, how is Haskell forcing the reification while SML does not?


In SML you can put side-effecting computaions in 'pure' functions --
functions whose type doesn't reveal that there are side effects. In Haskell
terms, every function is actually in the IO monad -- or every function is
given carte blanche to use unsafePerformIO depending upon how you look at
it. In semantic terms it is really a case of the former; from a programming
perspecive it is more like the latter; Standard ML is strict and I am
pretty sure this is only practical in a strict language. It is (IMHO)
deeply horrible, and possibly justifiable before monadic I/O was invented
(but not for me).

I am not advocating doing this (at all) but using it to illustrate a point.
In standard ML you can start doing effect-based things inside a function
without having to alter its type and they type of everything that uses it,
and so on.

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-25 Thread Arlen Cuss
 In standard ML you can start doing effect-based things inside a function 
 without having to alter its type and they type of everything that uses it, 
 and so on.
This in turn causes a break-down in the type-system where weak type variables 
are introduced.  We can see the pathological case for that here: 
http://www.cs.washington.edu/education/courses/cse505/00au/lectures/13-refs.txt

This makes regular things like curried function compositions unusable, because 
their polymorphicness goes away!  Such is the result of not encapsulating 
side-effects.

—Arlen

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-25 Thread Chris Dornan
On 24 June 2012 22:38, Tony Morris tonymor...@gmail.com wrote:

 **
 Odersky is repeatedly wrong on this subject and specifically for the claim
 that you quote, the only response is simply not true.


My point is this.

   1. The monadic approach to effects reifies functions into those that are
   'pure' and those that perform I/O -- you can tell which is which from the
   type.
   2. If you discover deep inside a function that you need after all to
   perform some I/O then the type of the function changes, and the type of
   everything that uses it changes, all the way back to the I/O trunk. The way
   these changed parts fit together changes radically. There is here an
   in-built instability here that is not *in itself* desirable.
   3. To compare, if you suddenly find you need to use a sin function
   deeply in a package providing pure trigonometric functions you don't have
   to rebuild everything. Likewise, if I discover I need to copy a file in an
   I/O system then this is not a big deal. Discovering (in Haskell) that you
   need to perfrom I/O somewhere that you thought didn't need to perform I/O
   is not like this.
   4. This instability, is in itself regretable I think. I think it is
   regreatble in the way that having to debug code is regretable, or having to
   write code at all is regreatable (why doesn't it write itself?). Its the
   cost of doing business.

Of couse Martin Odersky may have meant something else but this is the only
way I can make sense of it.

Making sense of part of what is being said and agreeing with it are quite
different -- never mind agreeing with the wider point.

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-25 Thread Anton Kholomiov
The class you're looking for is Applicative. The (*) operator handles
application of effectful things to effectful things, whereas ($)
handles the application of non-effectful things to effectful things.
This situation is interesting because it highlights the fact that there is
a distinction between the meaning of whitespace between function and
argument vs the meaning of whitespace between argument and argument.


`Applicative` is not enough for monads.
`Applicative` is like functor only for functions
with many arguments. It's good for patterns:

(a - b - c - d) - (m a - m b - m c - m d)

Monads are good for patterns

(a - b - c - m d) - (m a - m b - m c - m d)

So I can not express it with `Applicative`. My
analogy really breaks down on functions with
several arguments, since as you have pointed out there are
two white spaces. But I like the idea of using
one sign for normal and monadic  and maybe applicative
applications.

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-25 Thread Alberto G. Corona
My pocket explanation:

While e a function gives one only value of the codomain for each element of
the domain set (and thus it can be evaluated a single time), a category is
a generalization that accept many graphs that goes from each element of the
domain to the codomain. For that matter getChar can be understood
mathematically only using cathegory theory. To discover where the chain of
graphs goes each time, it is necessary to execute the chain of sentences.

Imperative languages works categorically every time, so they don´t need
an special syntax for doing so. Haskell permits to discriminate functional
code from normal categorical/imperative code, so the programmer and the
compiler can make use of the mathematical properties of functions. For
example, graph reduction thank to the uniqueness of  the paths.

Besides that, everything, functional or monadic is equally beatiful and
polimorphic. i don´t think that monadic code is less fine. It is
unavoidable and no less mathematical.

2012/6/25 Anton Kholomiov anton.kholom...@gmail.com

 The class you're looking for is Applicative. The (*) operator handles
 application of effectful things to effectful things, whereas ($)
 handles the application of non-effectful things to effectful things.
 This situation is interesting because it highlights the fact that there is
 a distinction between the meaning of whitespace between function and
 argument vs the meaning of whitespace between argument and argument.


 `Applicative` is not enough for monads.
 `Applicative` is like functor only for functions
 with many arguments. It's good for patterns:

 (a - b - c - d) - (m a - m b - m c - m d)

 Monads are good for patterns

 (a - b - c - m d) - (m a - m b - m c - m d)

 So I can not express it with `Applicative`. My
 analogy really breaks down on functions with
 several arguments, since as you have pointed out there are
 two white spaces. But I like the idea of using
 one sign for normal and monadic  and maybe applicative
 applications.

 Anton


 ___
 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] Martin Odersky on What's wrong with Monads

2012-06-25 Thread Ernesto Rodriguez
Well,

Monads are something optional at the end. Even the IO Monad is an optional
pattern with unsafePerformIO, but we use it because one of the reasons we
love Haskell is it's ability to differentiate pure and impure functions.
But sadly this is one of the traits we love about Haskell but others
dislike about it.

Cheers,

Ernesto Rodriguez

On Mon, Jun 25, 2012 at 2:23 PM, Alberto G. Corona agocor...@gmail.comwrote:

 My pocket explanation:

 While e a function gives one only value of the codomain for each element
 of the domain set (and thus it can be evaluated a single time), a category
 is a generalization that accept many graphs that goes from each element of
 the domain to the codomain. For that matter getChar can be understood
 mathematically only using cathegory theory. To discover where the chain of
 graphs goes each time, it is necessary to execute the chain of sentences.

 Imperative languages works categorically every time, so they don´t need
 an special syntax for doing so. Haskell permits to discriminate functional
 code from normal categorical/imperative code, so the programmer and the
 compiler can make use of the mathematical properties of functions. For
 example, graph reduction thank to the uniqueness of  the paths.

 Besides that, everything, functional or monadic is equally beatiful and
 polimorphic. i don´t think that monadic code is less fine. It is
 unavoidable and no less mathematical.

 2012/6/25 Anton Kholomiov anton.kholom...@gmail.com

 The class you're looking for is Applicative. The (*) operator handles
 application of effectful things to effectful things, whereas ($)
 handles the application of non-effectful things to effectful things.
 This situation is interesting because it highlights the fact that there is
 a distinction between the meaning of whitespace between function and
 argument vs the meaning of whitespace between argument and argument.


 `Applicative` is not enough for monads.
 `Applicative` is like functor only for functions
 with many arguments. It's good for patterns:

 (a - b - c - d) - (m a - m b - m c - m d)

 Monads are good for patterns

 (a - b - c - m d) - (m a - m b - m c - m d)

 So I can not express it with `Applicative`. My
 analogy really breaks down on functions with
 several arguments, since as you have pointed out there are
 two white spaces. But I like the idea of using
 one sign for normal and monadic  and maybe applicative
 applications.

 Anton


 ___
 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] Martin Odersky on What's wrong with Monads

2012-06-25 Thread MightyByte
Jonathan Geddes geddes.jonathan at gmail.com writes:
 Cafe,
 
 I was watching a panel on languages[0] recently and Martin Odersky (the 
creator of Scala) said something about Monads:
 
 
 What's wrong with Monads is that if you go into a Monad you have to change 
your whole syntax from scratch. Every single line of your program changes if 
you 
get it in or out of a Monad. They're not polymorphic so it's really the old 
days 
of Pascal. A monomorphic type system that says 'well that's all I do' ... 
there's no way to abstract over things.  [0, 53:45]
 
 
 Thoughts?

In my mind, his first sentence could be paraphrased as follows:

What's wrong with having a strongly typed mechanism for separating pure and 
effectful code is that pure code and effectful code are actually separate.

Of course every line of your program that uses a Foo will change if you switch 
to IO Foo instead.  If the two were indistinguishable, then you'd have an 
impure 
language instead of a pure one.  Furthermore, this isn't a characteristic 
specific to monads, it's the same for any type constructor whether it's a monad 
or not.

To Martin's credit, earlier in the talk (around 45:15) he makes the following 
statement:

What you need in the language is the ability to essentially reduce state.  And 
potentially what Scala doesn't do, but for instance Haskell does is to control 
state and purity, and I think that might be the next frontier.

Then at 50:15 he says, So right now, I think...in the world of effect checking 
we're about where we were with Pascal in terms of static typing.

It seems that his heart is in the right place, but he isn't aware of where we 
actually are right now, and probably doesn't fully appreciate the consequences 
of strongly typed purity.



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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-24 Thread Stephen Tetley
False!

You only have to change the parts of the program that need the effect
that the monad provides. A well designed program will likely have much
of its code in pure libraries. Think of the monadic code as a
scripting language that you bind your libraries together with to
make the program.

On 24 June 2012 06:31, Jonathan Geddes geddes.jonat...@gmail.com wrote:
 Cafe,
[SNIP]

 What's wrong with Monads is that if you go into a Monad you have to change
 your whole syntax from scratch. Every single line of your program changes if
 you get it in or out of a Monad. [SNIP]

 Thoughts?


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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-24 Thread Chris Dornan
What's wrong with Monads is that if you go into a Monad you have to
change your whole syntax
from scratch. Every single line of your program changes if you get it in
or out of a Monad. They're
not polymorphic so it's really the old days of Pascal. A monomorphic
type system that says 'well
that's all I do' ... there's no way to abstract over things.  [0,
53:45]

 [0] - http://css.dzone.com/articles/you-can-write-large-programs

I think the context of the question is important here. Odersky is asked why
provide all this elegant machinery
for doing functional things while  avoiding the difficult/critical parts --
the parts that deal with the effects. 

Odersky seems to be making three claims.

  * To move between functional and monadic code you have to completely
rewrite the code procedurally -- its
true and (IMHO) regrettable.

  * Monadic code is monomorphic: this appears to be seriously mistaken.
Monadic functions can be as polymorphic
as any non-monadic functions. (I have never wished the lambda-bound
variables introduced by 'do' statements
were somehow polymorphic.)

  * There is no way to abstract over monadic code: this also appears to be
mistaken as there are plenty
   of ways of abstracting while writing monadic code (using the very same
techniques you would use
   for non-monadic code).

Monads allow procedural code to be expressed procedurally and functional
code to be expressed functionally and
the type system ensures there are no mix ups. Expressing procedural code
functionally is as unnatural and error
prone as expressing functional code procedurally in my experience -- that
Haskell avoids compelling the programmer to
do either within its strongly-typed functional framework is (IMHO) its great
invention(*) and enduring strength.

Maybe someday someone will devise a way writing 'effects' code in a
strongly-typed functional framework
that doesn't force the programmer to commit each function to being either
procedural or functional -- or
better yet, do away with the need to write any effects code. Perhaps it has
been done already. (I don't doubt
folks have claimed to have done it.) But until there is a proven language
and tools that can do this, monads look
(to me, at least) like the best method for attacking 'effects' within a
strong functional framework.

Chris

(*) Monads were invented within the Haskell framework of course, after the
publication of the early reports and tools.



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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-24 Thread Alexander Solla
On Sun, Jun 24, 2012 at 12:27 AM, Chris Dornan ch...@chrisdornan.comwrote:


  * To move between functional and monadic code you have to completely
 rewrite the code procedurally -- its
true and (IMHO) regrettable.


It's false.  do-notation is completely optional.  It merely makes it easier
to extract multiple values from monadic actions, instead of the basic one
value per step bind provides.   Using join and (=) is just as easy as
do-notation, once you understand the idiom.

A monad is, first and foremost, a functor.  You can get at the underlying
algebra while statically ensuring relevant properties, using its functorial
or applicative or monadic interfaces.

For example:  consider a function that parses a string into a Foo.  It will
have a type like

parseFoo :: String - Maybe Foo

Should useFoo have the type

useFoo :: Maybe Foo - Maybe Bar

or

useFoo :: Foo - Bar?

The maybe functor/monad encapsulates the behavior of propagating
possible-undefinedness, so we are entirely justified in using its
functor/monad interface to simplify our types.  There is no reason to
redundantly have to pattern match on (Just foo) or (Nothing) when we can
abstract the control structure away and do

useFoo $ (parseFoo Foo 1) -- ($ == fmap)

or

(parseFoo Foo 1) = return . useFoo


Expressing procedural code
 functionally is as unnatural and error
 prone as expressing functional code procedurally in my experience -- that
 Haskell avoids compelling the programmer to
 do either within its strongly-typed functional framework is (IMHO) its
 great
 invention(*) and enduring strength.


Haskell didn't invent monads.  They have been in use since Grothendieck's
work in algebraic topology.  At least!  It is not hard to make a plausible
case that the Pythagoreans had a theory of monads in mind 2500 years ago.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-24 Thread Yves Parès
 To move between functional and monadic code you have to completely
rewrite the code procedurally

I don't like the way people segregate pure from monadic. Monadic code
*is* pure: it's written with completely pure Haskell and completely pure
combinators. As Alexander said, it's really important to say that 'do' is
just syntax over abstract combinators, and that it's *only for IO/ST* that
those combinators have something special.
This is why I do disagree with tutorials who begin by showing the 'do'
notation saying do IO with that.
If the beginner reads that and then puts his learning aside (because he was
interested to get some input about Haskell but has no time to continue for
the moment), he walks away with the false impression that you have do
blocks to do imperative stuff, and for the rest you just use normal
functions.
People are there because they've heard about the almighty *purely
functional* Haskell, I say let's give 'em what they came for:
getLine = \x - putStrLn (Hello  ++ x ++ !)
It's not complicated to understand the concept of an operator retrieving
the result of one operation and injecting it in the next.
Twist the syntax as you want if you think lambdas are not readable for
beginners, but still, if we begin by that, develop a little with a few more
examples and then say something like:
But it would be very cumbersome to have to write everything like that. But
don't worry, with great purity does not come great integrism!
Haskell people have been intelligent and brought you a special syntax to
write it more legibly, *but it's actually exactly the same you're doing!*
then the intuition that monads are just like pure code comes by itself.

This might be what leads people like Martin Odersky to false conclusions.

Amongst Haskellers I understand that we use this shortcut (pure VS monadic)
but as I said, towards non-Haskellers it's IMHO a bad idea to start
rightaway by making the difference between both.


Now, concerning Odersky's sentence specifically: To move between
functional and monadic code
you have to completely rewrite the code procedurally:
I don't see how that differs from any other language: monads are just
patterns (*), if you start with one method and then switch to another then
you'll have to refactor.

I'd say monads are actually better in that respect, since they can abstract
a lot due to their inherent EDSL nature (provide just one type and its set
of operations, and then you can change everything under the hood).

(*) And because of their pattern nature, they have the same drawbacks
than patterns in OO: people may (and will) try to fit triangles in round
holes, i.e. to use a monad where another abtraction (or no abstraction at
all) would be better.

2012/6/24 Chris Dornan ch...@chrisdornan.com

 What's wrong with Monads is that if you go into a Monad you have to
 change your whole syntax
from scratch. Every single line of your program changes if you get it in
 or out of a Monad. They're
not polymorphic so it's really the old days of Pascal. A monomorphic
 type system that says 'well
that's all I do' ... there's no way to abstract over things.  [0,
 53:45]

  [0] - http://css.dzone.com/articles/you-can-write-large-programs

 I think the context of the question is important here. Odersky is asked why
 provide all this elegant machinery
 for doing functional things while  avoiding the difficult/critical parts --
 the parts that deal with the effects.

 Odersky seems to be making three claims.

  * To move between functional and monadic code you have to completely
 rewrite the code procedurally -- its
true and (IMHO) regrettable.

  * Monadic code is monomorphic: this appears to be seriously mistaken.
 Monadic functions can be as polymorphic
as any non-monadic functions. (I have never wished the lambda-bound
 variables introduced by 'do' statements
were somehow polymorphic.)

  * There is no way to abstract over monadic code: this also appears to be
 mistaken as there are plenty
   of ways of abstracting while writing monadic code (using the very same
 techniques you would use
   for non-monadic code).

 Monads allow procedural code to be expressed procedurally and functional
 code to be expressed functionally and
 the type system ensures there are no mix ups. Expressing procedural code
 functionally is as unnatural and error
 prone as expressing functional code procedurally in my experience -- that
 Haskell avoids compelling the programmer to
 do either within its strongly-typed functional framework is (IMHO) its
 great
 invention(*) and enduring strength.

 Maybe someday someone will devise a way writing 'effects' code in a
 strongly-typed functional framework
 that doesn't force the programmer to commit each function to being either
 procedural or functional -- or
 better yet, do away with the need to write any effects code. Perhaps it has
 been done already. (I don't doubt
 folks have claimed to have done it.) But until there is a proven 

Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-24 Thread Anton Kholomiov
do-notation is just syntax in theory but in practice
it's difficult to avoid it. Try to write any OpenGL
program in terms of `=`,  `` and `return`.
I don't like to use `do` knowing that it's just
syntax sugar but sometimes it help a lot.
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-24 Thread Anton Kholomiov
Here is an half-baked idea how to make monads more functional.
It's too wild to be implemented in haskell.
But maybe you are interested more in ideas than implementations,
so let's start with monad class

class Monad m where
return :: a - m a
(=)  :: m a - (a - m b) - m b


I think monad's methods are misleading, let's rename them

class Monad m where
idM  :: a - m a
(*$) :: (a - m b) - m a - m b


We can see that `return` is a monadic identity and the `bind`
is an application in disguise. So now we have two applications.
It's standard `($)` and monadic `(*$)`. But they are application.
Well isn't it something like `plusInt` and `plusDouble`?
Maybe we can devise single class for application. Let's
imagine a special class `App`

class App ?? where
($) :: ???

As you can see it's defined so that we can fit
monads and plain functions in this framework. Moreover
if we redefine this class than whitespace is redefined
automatically! So `($)` really means *white space* in haskell.

`idM` is interesting too. In standard world we can safely
put `id` in any expression. So when we write

f = a + b

we can write

f = id (a + b)

or even

f = id ((id a) + (id b))

meaning doesn't change. So if we have special class `Id`

class Id f where
id :: ???

Again you can see that monads fit nicely in the type.
Why do we need this class? Whenever compiler gets an type mismatch,
it tries to apply method from `Id` class, if it's defined ofcourse.

But we have a class called `Category`, `id` belongs to it:

class Category (~) where
id   :: a ~ a
() :: (a ~ b) - (b ~ c) - (a ~ c)


Let's pretend that `()` is reversed composition `(.)`.
It's interesting to note that there is another formulation
of 'Monad' class. It's called Kelisli category.

class Kelisli m where
idK  :: a - m a
() :: (a - m b) - (b - m c) - (a - m c)

Here again let's forget about monad's `()` for a moment,
here it's composiotion. `Kleisli` is equivalent to `Monad`.

If we can define `Category` instance for `Kleisli`, so that
somehow this classes become unified on type level we
can define application in terms of composition like this:

f $ a = (const a  f) ()

And we can get application for monads (or kleislis :) ).

Implications:

Maybe someday you wrote a function like this:

foo :: Boo - Maybe Foo
foo x = case x of
1 - Just ...
2 - Just ...
3 - Just ...
4 - Just ...
5 - Just ...
6 - Just ...
7 - Just ...
_ - Nothing

with `idM` rule you can skip all Just's

You can use white space as monadic bind. So functional application
can become monadic on demand. Just switch the types.


Implementation:

I've tried to unify `Category` and `Kleisli` with no luck.
Here is a closest sletches:

simplest sketch requires type functions :(


instance Monad m = Category (\a b - a - m b) where
...


the other one too :(

class Category (~) where
type Dom (~) :: * - *
type Cod (~) :: * - *

id   :: Dom (~) a - Cod (~) a
() :: (Dom (~) a ~ Cod (~) b) - (Dom (~) b ~ Cod (~) c) - ...


instances

type Id a = a  -- :(

instance Monad m = Category (a - m b) where
type Dom (a - m b) = Id
type Cod (a - m b) = m

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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-24 Thread Chris Dornan
  To move between functional and monadic code you have
  to completely rewrite the code procedurally

 It's false.  do-notation is completely optional.  It merely makes it
 easier to extract multiple values from monadic actions, instead
 of the basic one value per step bind provides.   Using join
 and (=) is just as easy as do-notation, once you understand the idiom.

Odersky's point (and mine) was about moving between monadic and functional
code,
not eliminating a do notation (which is indeed a fairly trivial syntactic
device). To take
a fake and absurd example, there is a world of difference between

add:: Double - Double- IO Double

and the stock addition operator. (Perhaps you need to be very careful about
exceptions.) If you structure your program so that certain kinds of
arithmetic has
to be done monadically then everything that uses these operations must be
written
quite differently from how it would be with simple arithmetic operations.

You can argue that well it's just in the types -- you pays your money and
takes you
choice. (Viz., if your function works with effects then it should be
expressed in its type.)
But then this becomes the price of doing everything in a strong functional
framework. To take one counter example, the Standard ML combines functional
programming and effects without forcing this reification on the programmer.

I much prefer the Haskell way. But when it get criticized by a
non-Haskellers I try
to understand the criticism in the context it was phrased.

 Haskell didn't invent monads.

Indeed, that  sloppy phrasing on my part. I meant Haskell invented 'monads'
as
they have come to be understood in the Haskell context (a general
programming
device for encapsulating effects-based code in a functional programming
context),
not the original algebraic construct or its mathematical applications.

Chris



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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-24 Thread Alexander Solla
On Sun, Jun 24, 2012 at 2:48 AM, Chris Dornan ch...@chrisdornan.com wrote:

   To move between functional and monadic code you have
   to completely rewrite the code procedurally

  It's false.  do-notation is completely optional.  It merely makes it
  easier to extract multiple values from monadic actions, instead
  of the basic one value per step bind provides.   Using join
  and (=) is just as easy as do-notation, once you understand the idiom.

 Odersky's point (and mine) was about moving between monadic and functional
 code,
 not eliminating a do notation (which is indeed a fairly trivial syntactic
 device). To take
 a fake and absurd example, there is a world of difference between

add:: Double - Double- IO Double

 and the stock addition operator. (Perhaps you need to be very careful about
 exceptions.) If you structure your program so that certain kinds of
 arithmetic has
 to be done monadically then everything that uses these operations must be
 written
 quite differently from how it would be with simple arithmetic operations.



I sort of see where you're coming from.  But I'm having a hard time seeing
how this complaint would work with respect to Maybe and the other pure
monads.  In other words, I suspect the problem you're describing is
particular to IO and IO-like monads.

If a function isn't total, it is entirely natural to use Maybe to
encapsulate the potential for undefinedness. I would be extremely hesitant
to call

mAdd :: Int - Int - Maybe Int

monadic unless it was actually using a monadic interface to Maybe.
 Indeed, I would call it pure and functional.  Similarly for:

(++) :: [a] - [a] - [a]

The result types are monadic insofar as they have a free type variable, but
they are also entirely pure and functional.




 You can argue that well it's just in the types -- you pays your money and
 takes you
 choice. (Viz., if your function works with effects then it should be
 expressed in its type.)


Yes, this.  If you need a list, use a list.  If you need simple
undefinedness, use Maybe, etc.


 But then this becomes the price of doing everything in a strong functional
 framework. To take one counter example, the Standard ML combines functional
 programming and effects without forcing this reification on the programmer.


I don't know SML.  How is our list monadic and theirs not?  In
particular, how is Haskell forcing the reification while SML does not?
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-24 Thread Tony Morris
Odersky is repeatedly wrong on this subject and specifically for the
claim that you quote, the only response is simply not true.

On 24/06/12 15:31, Jonathan Geddes wrote:
 Cafe,

 I was watching a panel on languages[0] recently and Martin Odersky (the
 creator of Scala) said something about Monads:

 What's wrong with Monads is that if you go into a Monad you have to change
 your whole syntax from scratch. Every single line of your program changes
 if you get it in or out of a Monad. They're not polymorphic so it's really
 the old days of Pascal. A monomorphic type system that says 'well that's
 all I do' ... there's no way to abstract over things.  [0, 53:45]

 Thoughts?

 --J Arthur

 [0] - http://css.dzone.com/articles/you-can-write-large-programs



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


-- 
Tony Morris
http://tmorris.net/


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


Re: [Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-24 Thread wren ng thornton

On 6/24/12 5:41 AM, Anton Kholomiov wrote:

I think monad's methods are misleading, let's rename them

class Monad m where
 idM  :: a -  m a
 (*$) :: (a -  m b) -  m a -  m b

We can see that `return` is a monadic identity and the `bind`
is an application in disguise. So now we have two applications.
It's standard `($)` and monadic `(*$)`. But they are application.
Well isn't it something like `plusInt` and `plusDouble`?
Maybe we can devise single class for application. Let's
imagine a special class `App`

class App ?? where
 ($) :: ???

As you can see it's defined so that we can fit
monads and plain functions in this framework. Moreover
if we redefine this class than whitespace is redefined
automatically!


The class you're looking for is Applicative. The (*) operator handles 
application of effectful things to effectful things, whereas ($) 
handles the application of non-effectful things to effectful things. 
This situation is interesting because it highlights the fact that there 
is a distinction between the meaning of whitespace between function and 
argument vs the meaning of whitespace between argument and argument.


The desire to invoke ($) and (*) implicitly is known as idiom 
brackets. SHE provides this as syntactic sugar, and of course you can 
define your own version using iI and Ii as your brackets.




So `($)` really means *white space* in haskell.


Not entirely so, as noted above. Though yes, ($) denotes application in 
just the same way as function--argument whitespace does. However, the 
presence of ($) as an operator is helpful because it allows us to 
capture the syntax of our language, as in:


fmap ($x) fs

zipWith ($) fs xs

...

--
Live well,
~wren

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


[Haskell-cafe] Martin Odersky on What's wrong with Monads

2012-06-23 Thread Jonathan Geddes
Cafe,

I was watching a panel on languages[0] recently and Martin Odersky (the
creator of Scala) said something about Monads:

What's wrong with Monads is that if you go into a Monad you have to change
your whole syntax from scratch. Every single line of your program changes
if you get it in or out of a Monad. They're not polymorphic so it's really
the old days of Pascal. A monomorphic type system that says 'well that's
all I do' ... there's no way to abstract over things.  [0, 53:45]

Thoughts?

--J Arthur

[0] - http://css.dzone.com/articles/you-can-write-large-programs
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe