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: Announcement: Real World Haskell - Reading   Group (Jeff Greer)
   2.  Re: Announcement: Real World Haskell - Reading   Group
      (Benjamin L. Russell)
   3. Re:  Help using Type Families (MAN)
   4.  Parsec and Validation (Vladimir Solmon)
   5. Re:  Parsec and Validation (Ozgur Akgun)
   6. Re:  Parsec and Validation (Brandon S Allbery KF8NH)
   7. Re:  doc on accessing C struct binary data (Dean Herington)
   8. Re:  Parsec and Validation (Stephen Tetley)


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

Message: 1
Date: Sat, 31 Jul 2010 12:32:57 -0500
From: Jeff Greer <[email protected]>
Subject: [Haskell-beginners] Re: Announcement: Real World Haskell -
        Reading Group
To: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset="iso-8859-1"

Hi Russel,

Thanks for the suggestion to start a Haskell Reading Group mail list. At the
current time, I can not fit it into my schedul...  full time teaching job,
gard school, and family....

I hope some find the reading group useful.

-- 
http://teacherwikiweb.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
http://www.haskell.org/pipermail/beginners/attachments/20100731/0883e8f0/attachment-0001.html

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

Message: 2
Date: Sun, 01 Aug 2010 02:54:58 +0900
From: [email protected] (Benjamin L. Russell)
Subject: [Haskell-beginners] Re: Announcement: Real World Haskell -
        Reading Group
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=utf-8

Jeff Greer <[email protected]> writes:

> Hi Russel,Thanks for the suggestion to start a Haskell Reading Group mail 
> list. At the current time, I can not fit it into my schedul...  full time 
> teaching job, gard school, and family....I hope some find the reading group 
> useful.
> -- http://teacherwikiweb.com

My pleasure.  Incidentally, another great book I would suggest for a
reading group would be _Programming in Haskell_ [1], by Graham Hutton.

Does anybody have any plans to start a reading group for this book?

-- Benjamin L. Russell

[1] Hutton, Graham. _Programming in Haskell._ Cambridge: Cambridge
University Press,
2007. Print. <http://www.cs.nott.ac.uk/~gmh/book.html>.
-- 
Benjamin L. Russell  /   DekuDekuplex at Yahoo dot com
http://dekudekuplex.wordpress.com/
Translator/Interpreter / Mobile:  +011 81 80-3603-6725
"Furuike ya, kawazu tobikomu mizu no oto." -- Matsuo Basho^ 



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

Message: 3
Date: Sat, 31 Jul 2010 15:21:52 -0300
From: MAN <[email protected]>
Subject: Re: [Haskell-beginners] Help using Type Families
To: Antoine Latter <[email protected]>
Cc: [email protected]
Message-ID: <1280600512.5277.2.ca...@dy-book>
Content-Type: text/plain; charset="UTF-8"

Thank you, Antoine! I hadn't picked up on that. It worked perfectly.
You are right about this solution being too complex, too. It is. But I
admit to be more stubborn than allowed :D

El vie, 30-07-2010 a las 22:05 -0500, Antoine Latter escribió:
> On Fri, Jul 30, 2010 at 5:06 PM, MAN <[email protected]> wrote:
> > I desperately need help with this little predicament I got myself into.
> > I thought It'd be nice to write a piece of code that would wrap around
> > an older function, which given a bunch of parameters produces a plot (a
> > file) in the working directory. This new code receives the parameters
> > first, and only if the plot is not already present in the directory,
> > should pass the parameters to (and run) the wrapped function.
> >
> > With that in mind I've defined the following type class. The older
> > function is treated as an anonymous 'muscle', capable of taking its
> > parameters ordered in some structure unknown.
> >
> >> class Show parType => MuscleCapable parType where
> >>   -- | This could be a list or a tuple, etc. Whatever way of
> > implementing it, it
> >>   --   contains all necessary parameters to make the muscle produce a
> > resource.
> >>   --   Notice that this definition forces the type of ALL the
> > parameters of
> >>   --   the wrapped up muscle to be the same.
> >>   data Parameters parType
> >>
> >>   -- | A way to obtain the values of a @Parameters a@, for printing
> > purposes
> >>   listOfParams :: Parameters parType -> [parType]
> >>
> >>   -- | This wrapper around the muscle function will allow me to
> > produce a
> >>   --   resource on demand.
> >>   muscle :: Parameters parType -> IO FilePath
> >
> > But when trying to use that, I get different errors at compile time
> > related to my (mis)use of type families, most of which are above my
> > head.
> > I use this dummy code to test the mechanism:
> >
> >> data ThreeTuple a = T3 a a a
> >>
> >> listFromThreeTuple :: ThreeTuple a -> [a]
> >> listFromThreeTuple (T3 x y z) = [x,y,z]
> >>
> >> fun (T3 x y z) = do
> >>   withFile "output.out" WriteMode $ flip hPutStrLn (concatMap show
> > [x,y,z])
> >>   return "output.out"
> >>
> >> instance MuscleCapable Int where
> >>   data Parameters Int = ThreeTuple Int
> >>   listOfParams = listFromThreeTuple
> >>   muscle = fun
> >
> > This fires the following error in GHC (I do add the TypeFamilies
> > LANGUAGE pragma):
> > """
> >    Couldn't match expected type `Parameters Int'
> >           against inferred type `ThreeTuple Int'
> >      NB: `Parameters' is a type function
> > """
> >
> > If I use a similar data type without type parameters:
> >
> >> data ThreeTuple = T3 Int Int Int
> >
> > And modify the above snippet accordingly, I get the same thing:
> > """
> >    Couldn't match expected type `Parameters Int'
> >           against inferred type `ThreeTuple'
> >      NB: `Parameters' is a type function
> >    In the expression: listFromThreeTuple
> >    In the definition of `listOfParams':
> > """
> >
> > Whatever alternative I try (and I have gone far along the trial-error
> > path) inevitably yields those errors for both lines implementing
> > 'listOfParams' and 'muscle'.
> >
> > Could somebody help me understand what's going on? I'm really lost at
> > this point.
> >
> >
> > PS: My first attempt at the class used 'type' to define the associated
> > type. I had to switch to 'data' due to problems regarding the chosen
> > type not being _injective_. GHC error messages and the paper "Fun with
> > type functions" helped on that.
> >
> 
> The error is with your data instance declaration:
> 
> > data Parameters Int = ThreeTuple Int
> 
> You're treating a data declaration as if it were a type declaration -
> a data declaration needs to have a constructor, something like:
> 
> > data Paramter Int = ParamInt (ThreeTuple Int)
> 
> would be more likely to type check.
> 
> Then you'd have to pattern match on the constructor to deconstruct it.
> 
> 
> Type errors aside, all of this looks really really complicated, and
> from what you're describing I'm not sure it needs to be.
> 
> Why not just have two functions, one which wraps around the first? Or
> if you want to write code in a reusable manner, ordinary higher-order
> functions work well:
> 
> > writeToFileIfNonExistent :: FilePath -> (FilePath -> IO ()) -> IO ()
> > writeToFileIfNonExistent path action
> >  = do
> >   exists <- doesFileExist path
> >   unless exists $ action path
> >   return ()
> 
> > coreFileWritingFunction :: Param1 -> Param2 -> Param3 -> FilePath -> IO ()
> > coreFileWritingFunction p1 p2 p3 path = withFile path WriteMode $ \handle 
> > -> ...
> 
> > slickNewWrapper :: Param1 -> Param2 -> Param3 -> FilePath -> IO ()
> > slickNewWrapper p1 p2 p3 = writeToFileIfNonExistent $ 
> > coreFileWritingFunction p1 p2 p3
> 
> I've chosen silly names for my functions, but I hope you get the idea.
> Don't hesitate to respond if you have any questions.
> 
> Antoine




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

Message: 4
Date: Sat, 31 Jul 2010 12:57:07 -0700
From: Vladimir Solmon <[email protected]>
Subject: [Haskell-beginners] Parsec and Validation
To: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1

I'm attempting to use Parsec to write a parser for times and dates.
I'm aware of Data.Time.Format, but it doesn't offer the flexibility I
need for this project.

My current code (see below) uses Control.Monad.guard to validate the
numeric values for hours and minutes inside the parser. The problem
I'm running into is that checking for errors in the parsing code
causes Text.Parsec.Combinator.choice (in the time function below) to
fail and return an error if it cannot parse input using the first
option (tTimeHourMin), even if the input should match the second
option (t24hrClock).

I have several questions:

Why is choice failing in the time function below?

Is there a better way to do numeric validation while parsing?

Should I only use Parsec to validate that the input is syntactically
correct and do the numeric validation elsewhere?

What are some good examples of validating input using Parsec?


Here is a bit of the code I'm working with:

time :: Parser TimeOfDay
time = choice [ tTimeHourMin,
                          t24hrClock
                       ]

tTimeHourMin :: Parser TimeOfDay
tTimeHourMin = do
    hour <- range (0, 23)
    oneOf " :,."
    min <- range (0, 59)
    return (TimeOfDay hour min 0)

t24hrClock :: Parser TimeOfDay
t24hrClock = do
    (h, m) <- splitAt 2 <$> count 4 digit
    let hour = read h
    let min = read m
    guard (hour >= 0 && hour <= 23 && min >= 0 && min <= 59)
      <?> printf "24hr time represented as hhmm"
    return (TimeOfDay hour min 0)

range :: (Int,Int) -> Parser Int
range (lower, upper) = do
   t <- read <$> many1 digit
   guard (t >= lower && t <= upper)
     <?> printf "integer in range [%d,%d]" lower upper
   return t


Thanks for any suggestions,

vladimir


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

Message: 5
Date: Sat, 31 Jul 2010 21:05:28 +0100
From: Ozgur Akgun <[email protected]>
Subject: Re: [Haskell-beginners] Parsec and Validation
To: Vladimir Solmon <[email protected]>
Cc: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset="utf-8"

Could you try it with try's:

time :: Parser TimeOfDay
time = choice $ map try [ tTimeHourMin, t24hrClock ]

In a very informal and loose description, if tTimeHourMin consumes some
input before failing, parsec gives up.

Best,
Ozgur

On 31 July 2010 20:57, Vladimir Solmon <[email protected]> wrote:

> time :: Parser TimeOfDay
> time = choice [ tTimeHourMin,
>                           t24hrClock
>                        ]
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
http://www.haskell.org/pipermail/beginners/attachments/20100731/53b73f5e/attachment-0001.html

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

Message: 6
Date: Sat, 31 Jul 2010 16:11:28 -0400
From: Brandon S Allbery KF8NH <[email protected]>
Subject: Re: [Haskell-beginners] Parsec and Validation
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=UTF-8

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 7/31/10 15:57 , Vladimir Solmon wrote:
> time :: Parser TimeOfDay
> time = choice [ tTimeHourMin,
>                           t24hrClock
>                        ]

If the parse of tTimeHourMin fails after reading some characters (most
probably, at the oneOf because it has been fed a t24hrClock value), those
characters remain read and t24hrClock will pick up where the oneOf failed,
then itself fail because all the digits were read by the many1 in range.  To
prevent this, resetting to where tTimeHourMin started its parse, wrap it in
a try:

> time = choice [ try tTimeHourMin
>               , t24hrClock
>               ]

- -- 
brandon s. allbery     [linux,solaris,freebsd,perl]      [email protected]
system administrator  [openafs,heimdal,too many hats]  [email protected]
electrical and computer engineering, carnegie mellon university      KF8NH
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.10 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkxUg28ACgkQIn7hlCsL25WvWwCfd+a9hGc2iS/Gxph+SjDKOuIg
L6cAoIbGGUojYjmruoo3vsiu9HGB8kMl
=cndm
-----END PGP SIGNATURE-----


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

Message: 7
Date: Sat, 31 Jul 2010 17:05:35 -0400
From: Dean Herington <[email protected]>
Subject: Re: [Haskell-beginners] doc on accessing C struct binary data
To: Sean Perry <[email protected]>,  Stephen Tetley
        <[email protected]>, [email protected]
Message-ID: <a06240801c87a3d30a...@[10.0.1.4]>
Content-Type: text/plain; charset="us-ascii" ; format="flowed"

At 11:40 PM -0700 7/30/10, Sean Perry wrote:
>I would like to read C structs that have been written to disk as binary
>data. Is there a reference on doing this somewhere. The IO is not too
>hard, but how do I mimic the C struct in Haskell and still honor the
>exact sizes of the various struct members?

At 9:11 AM +0100 7/31/10, Stephen Tetley wrote:
>Hi Sean
>
>Commonly people would use Data.Word and Data.Int to get sized
>integrals. There's no corresponding sized types for floats - if you're
>lucky your serialized C Structs won't use floats otherwise you'll have
>to dig out a reference manual to see how they are laid out.
>
>To actually read C-structs Data.Binary.Get should provide the
>primitives you need (getWord8, getWord16le, getWord16be, ...), you'll
>then have to assemble a parser using these primitives to read your
>struct.
>
>You might have to pay some attention to alignment - the C struct might
>be laid out with elements on byte boundaries (usually 4-byte) rather
>than directly adjacent. I suspect alignment is compiler dependent, its
>a long time since I looked at this but I believe C99 has pragmas to
>direct the compiler on alignment.
>
>Best wishes
>
>Stephen

I would recommend using hsc2hs instead, as it avoids having to 
emulate the C compiler, which is tedious and error-prone.  (See 
section 10.3 of the GHC User's Guide.)  In a nutshell, you write (the 
necessary parts of) your program in a modestly extended Haskell.  In 
an .hsc file you can #include C header files (no need to duplicate 
that code in Haskell!) and bring selected pieces of the C world 
(types, field offsets, ...) into Haskell.  The hsc2hs translator 
actually creates a C program from your .hsc file that, when executed, 
writes your .hs file, incorporating the needed knowledge from C land.

Dean


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

Message: 8
Date: Sat, 31 Jul 2010 22:47:31 +0100
From: Stephen Tetley <[email protected]>
Subject: Re: [Haskell-beginners] Parsec and Validation
Cc: [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1

Hello Vladimir

In general it is better to avoid the try combinator and left factor
the grammar instead.

Because parsers are functions you can abuse left factoring a bit,
parse the prefix in a top level combinator and supply the prefix to
the sub-parsers:

leftFactoredTime :: Parser TimeOfDay
leftFactoredTime = do
  hh   <- width2Num
  sep  <- optionMaybe (oneOf ";,.")
  case sep of
    Nothing -> tTimeHourMin hh
    Just _  -> t24hrClock hh

tTimeHourMin :: Int -> Parser TimeOfDay
tTimeHourMin hh = do
  mm <- width2Num
  return (TimeOfDay hh mm 0)


t24hrClock :: Int -> Parser TimeOfDay
t24hrClock hh = do
  mm <- width2Num
  return (TimeOfDay hh mm 0)


However in this case, the 24 hour clock and TimeHourMin are identical
functions, the separator is a McGuffin [*] so:

betterTime :: Parser TimeOfDay
betterTime = do
  hh    <- rangeP 0 23 width2Num
  _sep  <- optionMaybe (oneOf ";,.")
  mm    <- rangeP 0 59 width2Num
  return (TimeOfDay hh mm 0)

To parse ranges I would make a new combinator that takes a range plus
a number parser and returns a new number parser:


rangeP :: Int -> Int -> Parser Int -> Parser Int
rangeP hi lo p = do
  a <- p
  if (lo <= a && a <= hi) then return a else fail "out-of-range"

Finally avoiding using read is good when using Parsec. Parsec has
token parsers to read numbers, but here read can be avoided with this
one:

width2Num :: Parser Int
width2Num = do
   a <- digit
   b <- digit
   return $ (10*digitToInt a) + digitToInt b


digitToInt is in the Data.Char module.

[*] A plot device used by Alfred Hitchcock films to throw the viewer
off the scent.


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

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


End of Beginners Digest, Vol 25, Issue 61
*****************************************

Reply via email to