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:  Convert String to List/Array of Numbers (Brent Yorgey)
   2. Re:  Convert String to List/Array of Numbers (Daniel Fischer)
   3. Re:  Convert String to List/Array of Numbers (Daniel Fischer)
   4.  Debugging overlapping instances (mtl vs  transformers)
      (Paolo Losi)
   5.  Re: Debugging overlapping instances (mtl vs      transformers)
      (Paolo Losi)
   6.  specify type for a function in GHCi (Henry Olders)
   7. Re:  specify type for a function in GHCi (Felipe Lessa)
   8. Re:  Re: Debugging overlapping instances (mtl vs
      transformers) (Stephen Tetley)


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

Message: 1
Date: Wed, 8 Sep 2010 14:17:56 -0400
From: Brent Yorgey <[email protected]>
Subject: Re: [Haskell-beginners] Convert String to List/Array of
        Numbers
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii

On Wed, Sep 08, 2010 at 07:24:12PM +0200, Lorenzo Isella wrote:
> Hi Daniel,
> Thanks for your help.
> I have a couple of questions left
> (1) The first one is quite down to earth.
> The snippet below
> 
> ---------------------------------------------------
> main :: IO ()
> 
> main = do
>   txt <- readFile "mydata.dat"
> 
>   let dat = convert txt
> 
>   print dat -- this prints out my chunk of data
> 
>   return ()
> 
> convert x = lines x
> 
> -----------------------------------------------

Looks good.  Note that the return () is not necessary since 'print
dat' already results in ().

> pretty much does what it is supposed to do, but if I use this
> definition of convert x
> 
> convert x = map (map read . words) . lines x

That ought to be

  convert = map (map read . words) . lines

or alternatively

  convert x = map (map read . words) (lines x)

The dot (.) is function composition, which lets you make "pipelines"
of functions.  So the first one says "convert is the function obtained
by first running 'lines' on the input, and then running 'map (map read
. words)' on the output of 'lines'.  You can also say explicitly what
to do with the input x, as in the second definition.  These two
definitions are exactly equivalent.

> (2) This is a bit more about I/O in general. I start an action with
> "do" to read some files and I define outside the action some
> functions which are supposed to operate (within the do action) on the
> read data.
> Is this the way it always has to be? I read something about monads
> but did not get very far (and hope that they are not badly needed for
> simple I/O).

When you do I/O you are using monads whether you know it or not!  But
no, you don't need a deep understanding of monads to do simple I/O.

In any event, this has nothing to do with monads in general, but is
particular to IO.  And yes, this is the way it always has to be with
I/O: there is no way to "escape", that is, there is no function* with
the type

  escapeIO :: IO a -> a

The problem is that because of Haskell's laziness, if there were such
a function you would have no idea when all the effects (like reading a
file, writing to disk, displaying something on the screen) would
happen -- or they might happen twice, or not at all!  Because of
Haskell's purity, the compiler is free to reorder and schedule
computations however it likes, and throwing side effects into the mix
would simply wreak havoc.

> Am I on the right track here? And what is the benefit of this?

The benefit is precise control of side effects, and what is known as
"referential transparency": if you have a function of type

  Int -> Int

then you know for certain that it only computes a numerical function.
Calling it will never result in things getting written to disk or the
screen or anything like that, and calling it with the same input will
always give you the same result.  This is a very strong guarantee that
gives you powerful ways to reason about programs.

-Brent

* Actually, there is, but it is only for use in very special low-level
  sorts of situations by those who really know what they are doing.


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

Message: 2
Date: Wed, 8 Sep 2010 20:29:23 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Convert String to List/Array of
        Numbers
To: Lorenzo Isella <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="iso-8859-1"

On Wednesday 08 September 2010 19:24:12, Lorenzo Isella wrote:
> Hi Daniel,
> Thanks for your help.
> I have a couple of questions left
> (1) The first one is quite down to earth.
> The snippet below
>
> ---------------------------------------------------
> main :: IO ()
>
> main = do
>    txt <- readFile "mydata.dat"
>
>    let dat = convert txt
>
>    print dat -- this prints out my chunk of data
>
>    return ()

That `return ()' is superfluous, print already has the appropriate type,

print :: Show a => a -> IO ()

return () is only needed to

- fill in do-nothing branches, if condition then doSomething else return () 
or
case expression of
    pat1 -> doSomething
    pat2 -> doSomethingElse
    _ -> return ()

- convert something to the appropriate type, e.g. if
action :: IO ExitCode
and you need an IO () in some place, then you use
action >> return ()

>
> convert x = lines x
>
> -----------------------------------------------
>
> pretty much does what it is supposed to do, but if I use this definition
> of convert x
>
> convert x = map (map read . words) . lines x
>
> I bump into compilation errors. Is that the way I am supposed to deal
> with your function?

Yes and no.
First of all, function application binds tighter than composition, so

convert x = map (map read . words) . lines x

is parsed as

convert x = (map ((map read) . words)) . (lines x)

which gives a type error because (lines x) :: [String], while the 
composition expects something of type (a -> b) as second argument.
The correct form of convert could be

convert x = (map (map read . words) . lines) x

or

convert x = map (map read . words) . lines $ x

or, point-free,

convert = map (map read . words) . lines

In the latter case, you have to give it a type signature,

convert :: Read a => String -> [[a]]

or disable the monomorphism restriction
({-# LANGUAGE NoMonomorphismRestriction #-} pragma in the file resp. the 
command-line flag -XNoMonomorphismRestriction), otherwise it'll likely give 
rise to other type errors.

Once that is fixed, your problems aren't over yet.

Then you get compilation errors because the compiler has no way to infer at 
which type to use read, should it try to read Integers, Bools, ... ?

Usually, in real code the type can be inferred from the context, at least 
enough for the defaulting rules to apply (if you pass dat to something 
expecting [[Bool]], the compiler knows it should use Bool's Read instance, 
if it's expecting (Num a => [[a]]), it can be defaulted (and will be 
defaulted to Integer unless you have an explicit default declaration 
stating otherwise).

In the code above, all the compiler can find out is that

dat :: (Read a, Show a) => [[a]]

GHC will compile it if you pass -XExtendedDefaultRules on the command line 
(or put {-# LANGUAGE ExtendedDefaultRules #-} at the top of the module), 
then the type variable a will be defaulted to () [which is rather useless].

More realistically, you need to tell the compiler the type of dat,

    let dat :: [[Integer]]  -- or ((Num a, Read a) => [[a]])
        dat = convert txt

>
> (2) This is a bit more about I/O in general. I start an action with "do"
> to read some files and I define outside the action some functions which
> are supposed to operate (within the do action) on the read data.

Yes, you define the functions that do the actual work as pure functions 
(mostly) and then bind them together in a - preferably small - main 
function doing the necessary I/O (reading data or configuration files, 
outputting results).

> Is this the way it always has to be? I read something about monads but
> did not get very far (and hope that they are not badly needed for simple
> I/O).

To do basic I/O, you don't need to know anything about monads, all you need 
is a little nowledge of the do-notation.

> Is there a way in Haskell to have the action return to the outside
> world e.g. the value of dat and then work with it elsewhere?

For the few cases where it's necessary, there is such a beast.
Its name begins with the word `unsafe', for good reasons (the full name is 
unsafePerformIO, available from System.IO.Unsafe).
When you're tempted to use it, ask yourself "Is this really a good idea?" 
(like if you're tempted to use goto in C, only more so - sometimes it is, 
but rarely).

> That is what I would do in Python or R, but I think I understood that
> Haskell's philosophy is different...

Well, you pass it as a parameter to other functions and IO-actions.

> Am I on the right track here? And what is the benefit of this?

Purity allows some optimisations that can't be done for functions which 
might have side-effects.
And it's much easier to reason about pure (side-effect-free) functions.

>
> Cheers
>
> Lorenzo


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

Message: 3
Date: Wed, 8 Sep 2010 20:45:14 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Convert String to List/Array of
        Numbers
To: [email protected]
Cc: Lorenzo Isella <[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="utf-8"

On Wednesday 08 September 2010 20:13:17, Chaddaï Fouché wrote:
> Given that the notion of argument number isn't quite right in Haskell

Since, strictly speaking, a function always takes exactly one argument.
Haskell is like mathematics in that respect.

But since saying "a function which takes an argument of type a, returning a 
function which takes an argument of type b, returning a function which 
takes an argument of type c, returning ..." is much more cumbersome than 
saying "a function taking five arguments of types a, b, c, d, e 
respectively and returning a value of type f", we are using the more 
convenient, albeit inexact, language habitually.
Haskell is like mathematics in that respect too.

Be aware however, that the same function may be referred to as a function 
taking three, four or perhaps six arguments in other circumstances.

> and that you should put a type signature on all exported functions

And also on nontrivial internal functions.

> which provides more exact information on the function behaviour
> anyway... I would say that point-free is worth it for the clarity it
> affords to the accustomed Haskeller

It takes a bit to get used to (having a mthematical background helps).
And point-freeing is not always a win in readability.
Judge on a case-by-case basis.

> (all but the most twisted
> functions written in point-free style will only take "one" argument
> anyway).

Possibly two.

foo = (sum .) . enumFromThenTo 0

hasn't yet clearly crossed the border.



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

Message: 4
Date: Thu, 09 Sep 2010 10:35:29 +0200
From: Paolo Losi <[email protected]>
Subject: [Haskell-beginners] Debugging overlapping instances (mtl vs
        transformers)
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

Hi all,

I'm definitely stuck with the migration of my project
from mtl to transformers. The use of transformer is
mandated by a new dependency that I need to add.

     Overlapping instances for Monad (Either String)
       arising from a use of `tstampToForecasts'
                    at ThreeLab/Gfs.hs:94:32-55
     Matching instances:
       instance (Control.Monad.Trans.Error.Error e) => Monad (Either e)
         -- Defined in Control.Monad.Trans.Error
       instance Monad (Either e)
         -- Defined in mtl-1.1.1.0:Control.Monad.Error

I really have no clue of who and why is bringing mtl instance in the
scope.

If I compile the file directly with:

ghc -package monads-tf -package transformers -hide-package mtl 
ThreeLab/Gfs.hs -c

I can successfully compile the module, so it seems the problem
is not specific to that module. But the compilation fails
if I do ghc -package monads-tf -package transformers -hide-package mtl 
--make Main.hs

What's the best practice to debug this problem?
What are the constraints of indirectly depending on both mtl
and transformers?

I'm really stuck :-/

Thanks
Paolo



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

Message: 5
Date: Thu, 09 Sep 2010 10:47:39 +0200
From: Paolo Losi <[email protected]>
Subject: [Haskell-beginners] Re: Debugging overlapping instances (mtl
        vs      transformers)
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

On 09/09/2010 10:35, Paolo Losi wrote:

> Overlapping instances for Monad (Either String)
> arising from a use of `tstampToForecasts'
> at ThreeLab/Gfs.hs:94:32-55
> Matching instances:
> instance (Control.Monad.Trans.Error.Error e) => Monad (Either e)
> -- Defined in Control.Monad.Trans.Error
> instance Monad (Either e)
> -- Defined in mtl-1.1.1.0:Control.Monad.Error

Forgot to say... that's the error I get using cabal build



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

Message: 6
Date: Thu, 09 Sep 2010 10:32:55 -0400
From: Henry Olders <[email protected]>
Subject: [Haskell-beginners] specify type for a function in GHCi
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii

Is there a way to specify the type for a function inside GHCi, that is, without 
creating a separate file and loading it in?

Henry






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

Message: 7
Date: Thu, 9 Sep 2010 11:35:27 -0300
From: Felipe Lessa <[email protected]>
Subject: Re: [Haskell-beginners] specify type for a function in GHCi
To: Henry Olders <[email protected]>
Cc: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=UTF-8

On Thu, Sep 9, 2010 at 11:32 AM, Henry Olders <[email protected]> wrote:
> Is there a way to specify the type for a function inside GHCi, that is, 
> without creating a separate file and loading it in?

Sure!

Prelude> let f x = x + 2
Prelude> :t f
f :: (Num a) => a -> a
Prelude> let g :: Int -> Int; g x = x + 2
Prelude> :t g
g :: Int -> Int

Cheers! =D

-- 
Felipe.


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

Message: 8
Date: Thu, 9 Sep 2010 17:07:08 +0100
From: Stephen Tetley <[email protected]>
Subject: Re: [Haskell-beginners] Re: Debugging overlapping instances
        (mtl vs transformers)
Cc: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1

Hi Paolo

What package are you trying build? - at a pinch it looks like it has
conflicting dependencies for the packages 'transformers' and mtl.


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

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


End of Beginners Digest, Vol 27, Issue 21
*****************************************

Reply via email to