Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Haskell-beginners] define action getInt like getLine

335 views
Skip to first unread message

kan...@gmx.de

unread,
Feb 2, 2010, 4:21:57 PM2/2/10
to begi...@haskell.org
Hi,
how can I write an action
getInt :: IO Int
that works like
getLine :: IO String
but for Int instead of String. I know that I can read the input with getLine and then convert it by using read, but don't know how to write it as an action. I tried
getInt :: IO Int
getInt read <- getLine
but that doesn't work.
--
Jetzt kostenlos herunterladen: Internet Explorer 8 und Mozilla Firefox 3.5 -
sicherer, schneller und einfacher! http://portal.gmx.net/de/go/atbrowser
_______________________________________________
Beginners mailing list
Begi...@haskell.org
http://www.haskell.org/mailman/listinfo/beginners

Rahul Kapoor

unread,
Feb 2, 2010, 4:39:45 PM2/2/10
to kan...@gmx.de, begi...@haskell.org
> Hi,
> how can I write an action
> getInt :: IO Int
> that works like
> getLine :: IO String

The most literal way to write getInt would be:

getInt :: IO Int
getInt = do
s <- getLine
return (read s)

which is just a more verbose version of:

getInt' = read `fmap` getLine

The above versions don't do any error checking, so you might
prefer a getInt :: IO Maybe Int which returns Nothing in case the input
is not an integer.

You should read up on Monadic IO in Haskell. The Real World Haskell book
is probably a good starting point.

Rahul

Daniel Fischer

unread,
Feb 2, 2010, 4:41:06 PM2/2/10
to begi...@haskell.org
Am Dienstag 02 Februar 2010 22:20:03 schrieb kan...@gmx.de:
> Hi,
> how can I write an action
> getInt :: IO Int
> that works like
> getLine :: IO String
> but for Int instead of String. I know that I can read the input with
> getLine and then convert it by using read, but don't know how to write
> it as an action. I tried getInt :: IO Int
> getInt read <- getLine
> but that doesn't work.

There are many possibilities.

The shortest is

getInt :: IO Int
getInt = readLn

another short and sweet is

getInt :: IO Int
getInt = fmap read getLine -- or liftM read getLine

But neither of these deals well with malformed input, if that's a
possibility to reckon with, use e.g. the reads function

getInt :: IO Int
getInt = do

inp <- getLine
case reads inp of
((a,tl):_) | all isSpace tl -> return a
_ -> handle malformed input

legajid

unread,
Feb 2, 2010, 5:01:45 PM2/2/10
to Rahul Kapoor, begi...@haskell.org
Hi,

here's another idea :

saisie_choix :: IO Int
saisie_choix=do
putStrLn "Type in 1 digit :"
xchoix <- getLine
if (length xchoix) /= 1 || head xchoix < '0' || head xchoix > '9'
then saisie_choix
else do
let nchoix=read xchoix::Int
return nchoix

or, with maybe :

{- -------------- MAYBE ------------------ -}

-- Fonction principale
mainmaybe=do
x <- lire
if isNothing x
then do
putStrLn "Donnee invalide"
else do
putStr " \b"

putStrLn ("Resultat : " ++ show (f x))

-- D�finition de la fonction de calcul
f Nothing = -9999
f (Just x) = 2 * x

-- Fonction d'IO qui valide la saisie
lire :: IO (Maybe Integer)
lire = do
-- saisie
xn <- getLine
let x=read xn ::Integer

-- validation
if x < 5
then do
return (Just x)
else do
return Nothing

Didier.

Rahul Kapoor a �crit :

Daniel Fischer

unread,
Feb 2, 2010, 5:18:17 PM2/2/10
to begi...@haskell.org
Am Dienstag 02 Februar 2010 23:06:41 schrieb legajid:
> -- D�finition de la fonction de calcul
> f Nothing = -9999
> f (Just x) = 2 * x

That's already in the standard libs:

ghci> :t maybe
maybe :: b -> (a -> b) -> Maybe a -> b
ghci> maybe (-9999) (*2) (Just $ fromEnum 'k')
214

kan...@gmx.de

unread,
Feb 7, 2010, 3:03:24 PM2/7/10
to begi...@haskell.org
thanks so far.
I used "getInt = fmap read getLine", because I think it's enough for me

I have to do it for a more complex case of reading an own data type (myDatatype) with is deriving Show and return an error otherwise.
I tried the following which didn't work:

readMyDatatype :: IO myDatatype
readMyDatatype = do
if readLn == (show readLn)
then return readLn
else do error "input error"


-------- Original-Nachricht --------
> Datum: Tue, 2 Feb 2010 22:39:07 +0100
> Von: Daniel Fischer <daniel.i...@web.de>
> An: begi...@haskell.org
> CC: kan...@gmx.de
> Betreff: Re: [Haskell-beginners] define action getInt like getLine

--
NEU: Mit GMX DSL �ber 1000,- � sparen!
http://portal.gmx.net/de/go/dsl02

Stephen Blackheath [to Haskell-Beginners]

unread,
Feb 7, 2010, 3:25:32 PM2/7/10
to kan...@gmx.de, begi...@haskell.org
Hi there,

Data types are required to start with a capital letter, so you'll have
to call it MyDatatype. I can't see where readLn is defined. Can you
paste a bit more of the code? I don't quite understand how your reading
of your own data type is meant to work - normally you would use read or
reads from the Read type class.

A more subtle point - because of the way lazy evaluation works, it is
generally better to use 'fail' rather than 'error' when in a monad. In
some monads it's possible that 'error' may do nothing.


Steve

kan...@gmx.de

unread,
Feb 8, 2010, 4:19:45 PM2/8/10
to Stephen Blackheath [to Haskell-Beginners], begi...@haskell.org
I want to read a "Month" from input and if this month issn't declared in my data type "Month" I want to throw an error message.

data Month = Jan | Feb | Mar | Apr | May | Jun | Jul | Ago | Sep | Oct | Nov | Dec deriving (Eq,Enum,Show)

-------- Original-Nachricht --------
> Datum: Mon, 08 Feb 2010 09:25:13 +1300
> Von: "Stephen Blackheath [to Haskell-Beginners]" <mutilating.caul...@blacksapphire.com>
> An: kan...@gmx.de
> CC: begi...@haskell.org

--
GRATIS f�r alle GMX-Mitglieder: Die maxdome Movie-FLAT!
Jetzt freischalten unter http://portal.gmx.net/de/go/maxdome01

kan...@gmx.de

unread,
Feb 8, 2010, 4:43:16 PM2/8/10
to Stephen Tetley, begi...@haskell.org
but I have to write the action
readMonth :: IO Month
on my own and still don't have an idea how to do it


-------- Original-Nachricht --------
> Datum: Mon, 8 Feb 2010 21:27:42 +0000
> Von: Stephen Tetley <stephen...@gmail.com>
> An:

> CC: begi...@haskell.org
> Betreff: Re: [Haskell-beginners] define action getInt like getLine

> Hello
>
> You can derive Read:


>
> > data Month = Jan | Feb | Mar | Apr | May | Jun | Jul | Ago | Sep | Oct |

> Nov | Dec deriving (Eq,Enum,Show,Read)
>
> This will certainly throw an error on failure (might not be an error
> you would want to transmit to a user though), and it will only read
> "Jan" not "jan" or "January"...
>
> Plenty of good suggestions in this thread:
>
> http://www.haskell.org/pipermail/haskell-cafe/2010-January/072177.html
>
>
> Best wishes
>
> Stephen

Daniel Fischer

unread,
Feb 8, 2010, 5:01:22 PM2/8/10
to begi...@haskell.org
Am Montag 08 Februar 2010 22:43:01 schrieb kan...@gmx.de:
> but I have to write the action
> readMonth :: IO Month
> on my own and still don't have an idea how to do it

Go take a look at

http://www.haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Prelude.html#v%3Aread
http://www.haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Prelude.html#v%3AreadLn
http://www.haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Prelude.html#v%3AgetLine

The documentation should help you.

Christian Maeder

unread,
Feb 9, 2010, 6:50:03 AM2/9/10
to kan...@gmx.de, begi...@haskell.org
kan...@gmx.de schrieb:

> but I have to write the action
> readMonth :: IO Month
> on my own and still don't have an idea how to do it

Your idea (below) to use show on all possible values and compare it to
the input line isn't that bad.

>> On 8 February 2010 21:19, <kan...@gmx.de> wrote:
>>> I want to read a "Month" from input and if this month issn't declared in
>> my data type "Month" I want to throw an error message.
>>> data Month = Jan | Feb | Mar | Apr | May | Jun | Jul | Ago | Sep | Oct |
>> Nov | Dec deriving (Eq,Enum,Show)

The Enum class allows you to create the list of all possible values
[Jan .. Dec]

This list can be turn into a lookup-list (for Data.List.lookup) by
map (\ a -> (show a, a))

>>>>> readMyDatatype = do
>>>>> if readLn == (show readLn)
>>>>> then return readLn
>>>>> else do error "input error"

This code is unfortunate, because "readLn" is an IO-Action (that cannot
be compared or shown). Even if you insert as first line:

readLn <- getLine

readLn is a String that will never be equal to "show readLn", because
show would add the double quotes. Also this shadowing of "readLn" is no
good practise and should be avoided, so better use:

str <- getLine

and use the string "str" to look it up in the list above.

Later on you may generalize readMonth to:

readMyDatatype :: (Show a, Enum a, Bounded a) => IO a

and also trim leading and trailing white space and case differences.

Cheers Christian

P.S. The functions read, readIO and readLn all have disadvantages in
case of errors. In the spirit of readIO it is possible to program
readMaybe, readEither or readM that are far more useful and missed very
often. Many such variants are somewhere, but one of readMaybe,
readEither or readM should be in a standard library.

readM would not be a generalization of readIO! But readIO could be
expressed using readM.

kan...@gmx.de

unread,
Feb 9, 2010, 4:41:30 PM2/9/10
to Stephen Tetley, begi...@haskell.org
ahhh, I didn't know that it's so simple with read :)

-------- Original-Nachricht --------
> Datum: Mon, 8 Feb 2010 22:26:59 +0000
> Von: Stephen Tetley <stephen...@gmail.com>
> An: kan...@gmx.de


> Betreff: Re: [Haskell-beginners] define action getInt like getLine

> Hello
>
> Upthread Daniel Fisher posted this one


>
> getInt :: IO Int
> getInt = fmap read getLine
>

> If you check the type of read
>
> *GHCi> :t read
> read :: (Read a) => String -> a
>
> 'reads' is polymorphic it will read anything from a String - well
> within reason, anything that is an instance of the Read type class.
> The "(Read a) => " part of the type signature indicates this
> constraint - that "a" ( the return type of the function read) must be
> an instance of Read.
>
> As I wrote, you can easily derive an instance of Read by adding Read
> to the deriving clause of your data type, so the next thing to do is
> write a function swapping as few parts from Daniel's example as
> possible:
>
> -- Here you have to make a change as you want a Month rather than an
> Int, so swap the ??? for what you want...
> getMonth :: IO ???
>
> -- The function definition can stay the same - none of the components
> in Daniel's definition actually depended on reading an Int:
> getMonth = fmap read getLine


>
>
>
> On 8 February 2010 21:43, <kan...@gmx.de> wrote:
> > but I have to write the action
> > readMonth :: IO Month
> > on my own and still don't have an idea how to do it
> >
> >

--

0 new messages