Send Beginners mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1. Re:  Re: Thinking about monads (Michael Mossey)
   2.  Re: Thinking about monads (Ertugrul Soeylemez)
   3.  Need Help (kaushal Pathak)
   4. Re:  Need Help (Michael Snoyman)
   5. Re:  Need Help (Rahul Kapoor)
   6. Re:  Need Help (Daniel Fischer)


----------------------------------------------------------------------

Message: 1
Date: Sun, 12 Apr 2009 14:02:40 -0700
From: Michael Mossey <[email protected]>
Subject: Re: [Haskell-beginners] Re: Thinking about monads
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed



Ertugrul Soeylemez wrote:
> Michael Mossey <[email protected]> wrote:
> 
>> I'm getting a better grasp on monads, I think. My original problem, I
>> think, was that I was still thinking imperatively. So when I saw this:
>>
>> class Monad m where
>>
>>     (>>=) :: m a -> (a -> m b) -> m b
>>
>> I didn't understand the "big deal". I thought, okay so you "do" something 
>> with the 
>> function (a -> m b) and you "arrive" at m b.  [...]
> 
> Think of f being a computation, in which something is missing.  It takes
> this something through a parameter.  So f is actually a function, which
> takes a value and results in a computation.  Another intuition:  f is a
> parametric computation.  Now if c0 is a computation, then
> 
>   c0 >>= f
> 
> is another computation built by feeding the result of c0 to f.  More
> graphically you've plugged the result cable of c0 to the input port of
> f.
> 
> As a real world example, consider a computation, which prints a value x:
> 
>   print x
> 
> That x has to come from somewhere, so this should actually be a function
> of some value x:
> 
>   \x -> print x
> 
> If that x should come from another computation, then (>>=) comes into
> play.  You can pass the result of one computation to the above one.  For
> example, if x comes from the result of getChar, you can write:
> 
>   getChar >>= \x -> print x
> 
> or simply:
> 
>   getChar >>= print
> 

Well, here are my thoughts. I know what you write is the way monads are 
introduced in 
most of the texts I've seen, but to the eyes of an imperative programmer, 
nothing 
"special" is going on. Let's give an example (but replace getChar by something 
deterministic). When I see

thing1 >>= thing2

I think to myself, this is basically the same as:

(Example A)
f input = result'
   where result = thing1 input
         result' = thing2 result

But it's not the same, because certain problems arise. What's special about 
monads is 
the way they are used and the particular problem they are trying to solve. For 
example, here are some problems we need to solve:

(1) how do you pass state from one function to the next in the most elegant way 
(avoiding the need to make complicated data types and having the ability to 
hide 
implementation details)

(2) how do you deal with errors? how do you "return early" from a set of 
computations 
that have hit a wall?

I confess I have not read any chapters on monads themselves, but I have 
finished 
Chapter 10 of Real World Haskell, which is mostly about motivating monads and 
implementing something very close to them. They use an operator they call ==>, 
which 
is nearly identical to >>=.

I see one answer to (1). Something like

(Example B)
f input =
    thing1 input >>= \result ->
    thing2 result >>= \result' ->
    return (result, result')

separates the idea of the state we passing "down the chain" from the results we 
get. 
I'll rewrite example (A) above, to be more explicit about what we are trying to 
do:

(Example C)
f state = (result, result')
   where (result, state')   = thing1 state
         (result', state'') = thing2 result state'


In example (B), the results are naturally available because they are arguments 
to 
functions, and all functions further down the chain are nested within them.

Now about problem (2)? The way the >>= operator is defined, it allows 
"short-circuiting" any remaining functions after we get a bad result. If the 
state is 
Maybe or Either, we can define >>= such that a result of Nothing or Left causes 
all 
remaining functions to be skipped. We could do this without monads, but it 
would look 
very ugly.

As a beginner, I'm not trying to lecture anyone, but putting down my thoughts 
so I 
can get feedback. I feel there's no way to "understand" monads without 
understanding 
the motivation of the problem we are trying to solve, or without seeing 
specific 
implementations. Chapter 10 of Real World Haskell provides a lot of motivation 
by 
showing early awkward attempts to solve these problems.

Regards,
Mike


------------------------------

Message: 2
Date: Mon, 13 Apr 2009 04:33:19 +0200
From: Ertugrul Soeylemez <[email protected]>
Subject: [Haskell-beginners] Re: Thinking about monads
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=US-ASCII

Hello Michael,

you're basically trying to give monads a better name.  Don't forget that
they are an abstract structure, which means that trying to find
intuitions or motivations is the same as trying to find real world
examples.

Monads are not a way to pass the result of some function to another
function.  We've got function composition for that.  Short-circuiting is
a feature of particular monads like Maybe, and as you said, you could
well do without them.  In Haskell, monads are an abstract combinator
class, which brings you mainly two advantages:  Generalization of
functionality and impure operations encapsulated in pure objects.

Those objects are the monadic values, which can be interpreted in a
number of ways.  I like to interpret them as computations, and this is
probably the most common interpretation.  Have a look at this:

  x :: Maybe Integer
  x = Just 3

As you already know, Maybe is a monad.  Just 3 is not a value right
away.  It is a computation, which results in 3.  The result of
computations may have a certain structure.  Maybe allows lack of a
result (the Nothing computation), which adds structure to the result.
The list type is also a monad.  It adds structure in that it allows
arbitrarily many results.  Monads also allow you to combine computations
(pass the result of one computation to another) in a structure-specific
manner.  In the Maybe monad, this is the short-circuiting you mentioned,
if there is no result.  In the list monad, each of the results is passed
and all individual results are collected in a larger result list
(non-determinism).

The big feature is that you can write code, which disregards this
structure.  This is what I referred to as generalization of
functionality.  Have a look at the sequence function from Control.Monad:

  sequence :: [m a] -> m [a]

Its type already suggests, what it does.  It takes a list of
computations and gives a computation, which results in the list of the
corresponding results.  Example:

  sequence [Just 3, Just 4, Just 5]
  = Just [3, 4, 5]

  sequence [[1,2], [3,4,5]]
  = [[1,3], [1,4], [1,5], [2,3], [2,4], [2,5]]

To understand the second example, view the list monad as a way to encode
non-determinism.  I've written more about this in section 11 of my
monads tutorial [1].

As said, the big advantage here is that you can write the sequence
function in a way, which completely disregards the underlying structure
implemented through the actual monad, such that you don't need to
rewrite it for each monad:

  sequence [] = return []
  sequence (c:cs)
    = c >>= \r ->
      sequence cs >>= \rs ->
      return (r:rs)

or by using the mapM function:

  sequence = mapM id

So Haskell monads help you to generalize functionality in the same way
as group theory and category theory help you to generalize proofs.

I hope, this helps.


Greets,
Ertugrul.


[1] http://ertes.de/articles/monads.html#section-11


Michael Mossey <[email protected]> wrote:

> 
> 
> Ertugrul Soeylemez wrote:
> > Michael Mossey <[email protected]> wrote:
> > 
> >> I'm getting a better grasp on monads, I think. My original problem, I
> >> think, was that I was still thinking imperatively. So when I saw this:
> >>
> >> class Monad m where
> >>
> >>     (>>=) :: m a -> (a -> m b) -> m b
> >>
> >> I didn't understand the "big deal". I thought, okay so you "do" something 
> >> with the 
> >> function (a -> m b) and you "arrive" at m b.  [...]
> > 
> > Think of f being a computation, in which something is missing.  It takes
> > this something through a parameter.  So f is actually a function, which
> > takes a value and results in a computation.  Another intuition:  f is a
> > parametric computation.  Now if c0 is a computation, then
> > 
> >   c0 >>= f
> > 
> > is another computation built by feeding the result of c0 to f.  More
> > graphically you've plugged the result cable of c0 to the input port of
> > f.
> > 
> > As a real world example, consider a computation, which prints a value x:
> > 
> >   print x
> > 
> > That x has to come from somewhere, so this should actually be a function
> > of some value x:
> > 
> >   \x -> print x
> > 
> > If that x should come from another computation, then (>>=) comes into
> > play.  You can pass the result of one computation to the above one.  For
> > example, if x comes from the result of getChar, you can write:
> > 
> >   getChar >>= \x -> print x
> > 
> > or simply:
> > 
> >   getChar >>= print
> > 
> 
> Well, here are my thoughts. I know what you write is the way monads are 
> introduced in 
> most of the texts I've seen, but to the eyes of an imperative programmer, 
> nothing 
> "special" is going on. Let's give an example (but replace getChar by 
> something 
> deterministic). When I see
> 
> thing1 >>= thing2
> 
> I think to myself, this is basically the same as:
> 
> (Example A)
> f input = result'
>    where result = thing1 input
>          result' = thing2 result
> 
> But it's not the same, because certain problems arise. What's special about 
> monads is 
> the way they are used and the particular problem they are trying to solve. 
> For 
> example, here are some problems we need to solve:
> 
> (1) how do you pass state from one function to the next in the most elegant 
> way 
> (avoiding the need to make complicated data types and having the ability to 
> hide 
> implementation details)
> 
> (2) how do you deal with errors? how do you "return early" from a set of 
> computations 
> that have hit a wall?
> 
> I confess I have not read any chapters on monads themselves, but I have 
> finished 
> Chapter 10 of Real World Haskell, which is mostly about motivating monads and 
> implementing something very close to them. They use an operator they call 
> ==>, which 
> is nearly identical to >>=.
> 
> I see one answer to (1). Something like
> 
> (Example B)
> f input =
>     thing1 input >>= \result ->
>     thing2 result >>= \result' ->
>     return (result, result')
> 
> separates the idea of the state we passing "down the chain" from the results 
> we get. 
> I'll rewrite example (A) above, to be more explicit about what we are trying 
> to do:
> 
> (Example C)
> f state = (result, result')
>    where (result, state')   = thing1 state
>          (result', state'') = thing2 result state'
> 
> 
> In example (B), the results are naturally available because they are 
> arguments to 
> functions, and all functions further down the chain are nested within them.
> 
> Now about problem (2)? The way the >>= operator is defined, it allows 
> "short-circuiting" any remaining functions after we get a bad result. If the 
> state is 
> Maybe or Either, we can define >>= such that a result of Nothing or Left 
> causes all 
> remaining functions to be skipped. We could do this without monads, but it 
> would look 
> very ugly.
> 
> As a beginner, I'm not trying to lecture anyone, but putting down my thoughts 
> so I 
> can get feedback. I feel there's no way to "understand" monads without 
> understanding 
> the motivation of the problem we are trying to solve, or without seeing 
> specific 
> implementations. Chapter 10 of Real World Haskell provides a lot of 
> motivation by 
> showing early awkward attempts to solve these problems.
> 
> Regards,
> Mike



-- 
nightmare = unsafePerformIO (getWrongWife >>= sex)
http://blog.ertes.de/




------------------------------

Message: 3
Date: Sat, 11 Apr 2009 17:46:47 +0530
From: kaushal Pathak <[email protected]>
Subject: [Haskell-beginners] Need Help
To: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset="iso-8859-1"

Hi There,
   Here is a very simple haskell program I have written to find whether a
number is prime or not, which doesn't give me any compilation error but
gives following run-time error :

Any help would help me move ahead, I know that the type concepts is what I
am lacking, anly pointer to simple/good article/paper would definitely help.

Lots of thannx jut even to look at the mail :-)

Regards
Kaushal

*Run Time Error :*

kaushal > isPrime1 171

<interactive>:1:0:
    Ambiguous type variable `t' in the constraints:
      `Integral t'
        arising from a use of `isPrime1' at <interactive>:1:0-11
      `Floating t'
        arising from a use of `isPrime1' at <interactive>:1:0-11
      `RealFrac t'
        arising from a use of `isPrime1' at <interactive>:1:0-11
    Probable fix: add a type signature that fixes these type variable(s)
kaushal >

*Program :*

isPrime1 x =
    let canDivide num 0 = 0
        canDivide num 1 = 0
        canDivide num divisor = if ((mod num divisor) == 0) then 1
                                else canDivide num (divisor - 1)
    in
        if ( x == 1 )
        then putStrLn("1 is Neither prime nor composite!!!")
        else if ((canDivide x first_div) == 1)
             then putStrLn(show(x) ++ " is not a Prime Number!!!")
             else putStrLn(show(x) ++ " is a Prime Number!!!")
        where
        first_div :: Integral a => a ; first_div = round (sqrt x)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
http://www.haskell.org/pipermail/beginners/attachments/20090411/f855590c/attachment-0001.htm

------------------------------

Message: 4
Date: Mon, 13 Apr 2009 06:29:05 +0300
From: Michael Snoyman <[email protected]>
Subject: Re: [Haskell-beginners] Need Help
To: kaushal Pathak <[email protected]>
Cc: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset="utf-8"

On Sat, Apr 11, 2009 at 3:16 PM, kaushal Pathak <[email protected]> wrote:

>
>         first_div :: Integral a => a ; first_div = round (sqrt x)
>

Should in fact be

        first_div :: Integral a => a ; first_div = round (sqrt $
fromIntegral x)

Basically, sqrt has the type signature sqrt :: (Floating a) => a -> a,
meaning it only works on things like doubles. The rest of your code only
works on integral types. Your code compiles just fine because, in theory,
you could have a data structure which in an instance of both Integral and
Floating, but the argument you provide is probably just a regular old Int or
something like that (I can't be certain, as you have not provided the code
that calls isPrime1).

Let me know if you'd like further clarification.

Michael
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
http://www.haskell.org/pipermail/beginners/attachments/20090413/39540c00/attachment-0001.htm

------------------------------

Message: 5
Date: Sun, 12 Apr 2009 23:45:33 -0400
From: Rahul Kapoor <[email protected]>
Subject: Re: [Haskell-beginners] Need Help
To: kaushal Pathak <[email protected]>
Cc: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1

>  Here is a very simple haskell program I have written to find whether a
> number is prime or not, which doesn't give me any compilation error but
> gives following run-time error :
>

The type of isPrime1 function you have defined is inferred to be

isPrime1 :: (Integral a, RealFrac a, Floating a) => a -> IO ()

You can check this quickly using :t isPrime1 in GHCI.

When you try to run isPrime1 in GHCI you get a compile error
since the argument isPrime1 is an integer which does not
satisfy the three constraints (Integral, RealFrac and Floating).

You probably wanted to define isPrime1 to have the type
(Integer a) => a -> IO ()

Cheers,
Rahul


www.artquiver.com
What kind of art do you like?


------------------------------

Message: 6
Date: Mon, 13 Apr 2009 06:01:26 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Need Help
To: [email protected]
Cc: kaushal Pathak <[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="iso-8859-15"

Am Samstag 11 April 2009 14:16:47 schrieb kaushal Pathak:
> Hi There,
>    Here is a very simple haskell program I have written to find whether a
> number is prime or not, which doesn't give me any compilation error but
> gives following run-time error :
>
> Any help would help me move ahead, I know that the type concepts is what I
> am lacking, anly pointer to simple/good article/paper would definitely
> help.
>
> Lots of thannx jut even to look at the mail :-)
>
> Regards
> Kaushal
>
> *Run Time Error :*
>
> kaushal > isPrime1 171
>
> <interactive>:1:0:
>     Ambiguous type variable `t' in the constraints:
>       `Integral t'
>         arising from a use of `isPrime1' at <interactive>:1:0-11
>       `Floating t'
>         arising from a use of `isPrime1' at <interactive>:1:0-11
>       `RealFrac t'
>         arising from a use of `isPrime1' at <interactive>:1:0-11
>     Probable fix: add a type signature that fixes these type variable(s)
> kaushal >
>
> *Program :*
>
> isPrime1 x =
>     let canDivide num 0 = 0
>         canDivide num 1 = 0
>         canDivide num divisor = if ((mod num divisor) == 0) then 1
>                                 else canDivide num (divisor - 1)
>     in
>         if ( x == 1 )
>         then putStrLn("1 is Neither prime nor composite!!!")
>         else if ((canDivide x first_div) == 1)
>              then putStrLn(show(x) ++ " is not a Prime Number!!!")
>              else putStrLn(show(x) ++ " is a Prime Number!!!")
>         where
>         first_div :: Integral a => a ; first_div = round (sqrt x)

Make it first_div = round (sqrt $ fromIntegral x)

And use Bool for boolean expressions:

canDivide num 0 = False
canDivide num 1 = False
canDivide num divisor = num `mod` divisor == 0 || canDivide num (divisor -1)

The error happens because Haskell does no automatic type conversions.
In canDivide, you use mod on x, since the type of mod is

Prelude> :t mod
mod :: (Integral a) => a -> a -> a

both arguments of canDivide must belong to the same type which must be an 
Integral type.
The second argument of canDivide is first_div, which you defined as

first_div = round (sqrt x)

The type of sqrt is

Prelude> :t sqrt
sqrt :: (Floating a) => a -> a

so to call sqrt x, the type of x must belong to the Floating class, the result 
of sqrt has 
the same type as its argument.

Then you round the result of sqrt, the type of round is

Prelude> :t round
round :: (RealFrac a, Integral b) => a -> b

The argument of round is the result of sqrt, which has the same type as x, 
which also must 
belong to the class RealFrac for this to work.

So, for your function to work, its argument must have a type belonging to the 
three 
classes
Integral
Floating
RealFrac

That's perfectly legal, so the code compiles and isPrime1 has the type

isPrime1 :: (Integral a, Floating a, RealFrac a) => a -> IO ().

And when you type

isPrime1 171

at the prompt, ghci doesn't really know what to do, to know that, it must know 
the exact 
type of 171 (different types could expose different behaviour and might even 
lead to 
different results). Since all classes are standard classes and at least one of 
them is 
numeric, ghci tries then to default the type, looking for a type satisfying 
these 
constraints in the default list (Integer, Double is the default-default).

But there is no type which belongs to all three classes (unless you provide the 
instances 
for some type, and it wouldn't really make sense for a type to be Integral as 
well as 
Floating), so ghci gives up and reports that it couldn't resolve the type 
variable.

In situations like this, usually the remedy is inserting a few explicit 
conversion 
functions.



------------------------------

_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners


End of Beginners Digest, Vol 10, Issue 12
*****************************************

Reply via email to