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: Fwd: [Haskell-beginners] More Deserialization Woes
      (Daniel Fischer)
   2. Re:  upgrade Hackage show to QuickCheck 2 for     lambdabot
      (Jonas Almstr?m Dureg?rd)
   3. Re:  what's a proper way to make a Set    typeclass? and why is
      it not done already? (Brent Yorgey)
   4. Re: Fwd: [Haskell-beginners] More Deserialization Woes (Tom Hobbs)


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

Message: 1
Date: Tue, 6 Jul 2010 11:42:04 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: Fwd: [Haskell-beginners] More Deserialization Woes
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="utf-8"

On Tuesday 06 July 2010 11:15:12, Tom Hobbs wrote:
> Sorry, I meant to send this to the list, rather than just to Stephen
> (sorry for the Spam).
>
> Tom
>
>
> ---------- Forwarded message ----------
> From: Tom Hobbs <[email protected]>
> Date: Tue, Jul 6, 2010 at 10:12 AM
> Subject: Re: [Haskell-beginners] More Deserialization Woes
> To: Stephen Tetley <[email protected]>
>
>
> Hello again,
>
> I've been reading through various tutorials and they all put IO as the
> outermost monad, like you suggest.  However, I don't think that's what I
> want.
>
> My IO operation is reading from a network stream, not a file, so I want
> a failure halfway through should signify a complete failure.  So, I
> believe that the type signature for my function should be;
>
> ping  :: String -> PortNumber -> Maybe (IO [String])
>
> because the result "Just []" is a valid one and does not signify a
> failure.
>

Nevertheless, IO (Maybe [String]) is, I believe, the appropriate type.

>
> However, the result of "IO [Just "a", Just "b", Nothing, Nothing]" would
> signify that communication failed halfway through and would not make
> sense in my context.  This is what the advice seems to be suggesting I
> write.  But in this case, I'd prefer to return "Nothing" to signify that
> a problem occurred.

You can do that by applying sequence (at the type [Maybe String] -> Maybe 
[String]).

Say you have

ping0 :: args -> IO [Maybe String]

then you'd use

ping :: args -> IO (Maybe [String])
ping = fmap sequence ping0

>
> So my first question is; because I want to do something so different
> from the majority of the articles I've read; am I in a niche where my
> requirement makes sense, or does my requirement make no sense - a theory
> that is backed up by the fact that no one else seems to be doing that...
>
> Now, I'm not sure I can get there by myself, since I'm struggling to get
> the right incantation of catching errors but I'll keep plugging away at
> that for a while.
>
> But can someone help me with my next question also.
>
> Is it possible, to extract the values out of the IO monad so it can be
> used in pure functions.

Yes, but you needn't (and shouldn't in general).

The general pattern is

main = do
    someValues <- getDataIOAction
    let otherValues = pureStuff someValues
    outputIO otherValues

>
> For example, once ping has returned it's Maybe [IO String], I would like
> to be able to create another function such as;
>
> purePing :: String -> PortNumber -> Maybe [String]
> purePing a p = removeIOMonad (ping a p)
>                       where
>                       removeIOMonad Nothing = Nothing
>                       removeIOMonad []    = Just []
>                       removeIOMonad (x:xs)    = clevelDropIOMagic x :
> removeIOMonad xs
>
> ...or something...
>
> Once the IO [String] has been read from the stream, no further IO is
> necessary, so any other function should be able to just use the list and
> not worry about the IO stuff.
>
> Again my questions are, Is this an okay thing to do, or is my
> design/idea very, very wrong?
>
> Thanks again for the help,
>
> Tom


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

Message: 2
Date: Tue, 6 Jul 2010 11:49:31 +0200
From: Jonas Almstr?m Dureg?rd <[email protected]>
Subject: Re: [Haskell-beginners] upgrade Hackage show to QuickCheck 2
        for     lambdabot
To: Antoine Latter <[email protected]>
Cc: [email protected], haskell mailing list
        <[email protected]>
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1

For some reason the generate function is not in QC2.

Here's a quick fix:

\begin{code}
import Test.QuickCheck.Gen
import System.Random

generate :: Int -> StdGen -> Gen a -> a
generate n rnd (MkGen m) = m rnd' size
  where
   (size, rnd') = randomR (0, n) rnd
\end{code}

Perhaps it would be better to ask the QC maintainers to re-include
this function in the library...

/Jonas

On 3 July 2010 01:09, Antoine Latter <[email protected]> wrote:
> Including the café.
>
> On Jul 2, 2010 8:49 AM, "Mark Wright" <[email protected]> wrote:
>
> Hi,
>
> I'm trying to upgrade Hackage show to QuickCheck 2, after
> applying the diffs below (which may not be correct, since I am
> a beginner), I am left which this error message:
>
> runghc ./Setup.hs build
> Preprocessing library show-0.3.4...
> Building show-0.3.4...
> [4 of 4] Compiling ShowQ            ( ShowQ.hs, dist/build/ShowQ.o )
>
> ShowQ.hs:104:20: Not in scope: `generate'
>
> Compilation exited abnormally with code 1 at Fri Jul  2 23:07:17
>
> The error occurs in this method:
>
> tests :: Gen Result -> StdGen -> Int -> Int -> [[String]] -> IO String
> tests gen rnd0 ntest nfail stamps
>  | ntest == 500  = done "OK, passed" ntest stamps
>  | nfail == 1000 = done "Arguments exhausted after" ntest stamps
>  | otherwise = case ok result of
>       Nothing    -> tests gen rnd1 ntest (nfail+1) stamps
>       Just True  -> tests gen rnd1 (ntest+1) nfail (stamp result:stamps)
>       Just False -> return $ "Falsifiable, after "
>                               ++ show ntest
>                               ++ " tests:\n"
>                               ++ reason result
>   where
>      result      = generate (((+ 3) . (`div` 2)) ntest) rnd2 gen
>      (rnd1,rnd2) = split rnd0
>
> The QuickCheck 1 generate method is near the bottom this page:
>
> http://hackage.haskell.org/packages/archive/QuickCheck/1.2.0.0/doc/html/Test-QuickCheck.html
>
> but I can not find generate in QuickCheck 2.  I am wondering if
> you have any ideas on how to fix it?
>
> I'm trying to package lambdabot on Solaris.  I have already packaged
> the Haskell Platform and about 90 packages, they are in:
>
> http://pkgbuild.sourceforge.net/spec-files-extra/
>
> Thanks very much, Mark
>
> here are the diffs:
>
> goanna% diff -wc show-0.3.4-orig/ShowQ.hs show-0.3.4/ShowQ.hs
> *** show-0.3.4-orig/ShowQ.hs    Wed Jan 20 11:24:11 2010
> --- show-0.3.4/ShowQ.hs Fri Jul  2 23:07:13 2010
> ***************
> *** 12,22 ****
> --- 12,25 ----
>
>  import qualified Test.SmallCheck (smallCheck, Testable)
>  import Test.QuickCheck
> + import Test.QuickCheck.Arbitrary
>  import Data.Char
>  import Data.List
>  import Data.Word
>  import Data.Int
>  import System.Random
> + import Control.Exception (evaluate)
> + import Test.QuickCheck.Property (ok, stamp)
>
>  type T = [Int]
>  type I = Int
> ***************
> *** 23,36 ****
> --- 26,45 ----
>
>  instance Arbitrary Char where
>      arbitrary     = choose (minBound, maxBound)
> +
> + instance CoArbitrary Char where
>      coarbitrary c = variant (ord c `rem` 4)
>
>  instance Arbitrary Word8 where
>      arbitrary = choose (minBound, maxBound)
> +
> + instance CoArbitrary Word8 where
>      coarbitrary c = variant (fromIntegral ((fromIntegral c) `rem` 4))
>
>  instance Arbitrary Ordering where
>      arbitrary     = elements [LT,EQ,GT]
> +
> + instance CoArbitrary Ordering where
>      coarbitrary LT = variant 1
>      coarbitrary EQ = variant 2
>      coarbitrary GT = variant 0
> ***************
> *** 37,42 ****
> --- 46,53 ----
>
>  instance Arbitrary Int64 where
>    arbitrary     = sized $ \n -> choose (-fromIntegral n,fromIntegral n)
> +
> + instance CoArbitrary Int64 where
>    coarbitrary n = variant (fromIntegral (if n >= 0 then 2*n else 2*(-n) +
> 1))
>
>  instance (Integral a, Arbitrary a) => Arbitrary (Ratio a) where
> ***************
> *** 48,53 ****
> --- 59,65 ----
>                              else (b % a)
>                           else (a % b)
>
> + instance (Integral a, CoArbitrary a) => CoArbitrary (Ratio a) where
>    coarbitrary m = variant (fromIntegral $ if n >= 0 then 2*n else 2*(-n) +
> 1)
>      where n = numerator m
>
> ***************
> *** 87,93 ****
>         Just False -> return $ "Falsifiable, after "
>                                 ++ show ntest
>                                 ++ " tests:\n"
> !                                ++ unlines (arguments result)
>     where
>        result      = generate (((+ 3) . (`div` 2)) ntest) rnd2 gen
>        (rnd1,rnd2) = split rnd0
> --- 99,105 ----
>         Just False -> return $ "Falsifiable, after "
>                                 ++ show ntest
>                                 ++ " tests:\n"
> !                                ++ reason result
>     where
>        result      = generate (((+ 3) . (`div` 2)) ntest) rnd2 gen
>        (rnd1,rnd2) = split rnd0
> goanna%
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
>
>


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

Message: 3
Date: Tue, 6 Jul 2010 10:51:57 +0100
From: Brent Yorgey <[email protected]>
Subject: Re: [Haskell-beginners] what's a proper way to make a Set
        typeclass? and why is it not done already?
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=iso-8859-1

On Tue, Jul 06, 2010 at 01:35:41AM +0300, Markus Läll wrote:
> I started like this:
> 
> {-# LANGUAGE
>    MultiParamTypeClasses,
>    FlexibleInstances #-}
> 
> import qualified Data.List as L
> 
> class (Eq e) => Set s e where
>    empty :: s e
>    fromList :: [e] -> s e
>    ...
> 
> ..and started to implement it on a list:
> 
> instance (Eq e) => Set [] e where
>    empty = []
>    fromList xs = L.nub xs
> 
> But I can't understand, why there has to be a (Eq a) context to the
> Set instance of a list, when the class definition seems to already say
> it? It won't compile without it..

The class definition says that an Eq constraint is *required*, it does
not provide it.  'instance Set [] e' would promise that the instance
will work for *any* type e (even ones without an Eq instance), but the
class declaration requires that e must have an Eq instance.  Hence the
error.

> Secondly, why do I need FlexibleInstances -- it gives me an eror which
> I don't understand ("all instance types must be of the form T a1 ...
> an" and so on, and recommends to add the flexible instances.)

The Haskell98 standard is quite convervative when it comes to the
sorts of instances you are allowed to declare.  I think in this case
it is complaining about the fact that e is a variable and not a
particular type constructor; I agree that particular error is rather
hard to decipher.  In any case, enabling FlexibleInstances is quite
common and harmless.

> Also I couldn't find other elaborate Set typeclasses -- there seems to
> be only the "Set a" type. Why is that(?), because you could use other
> datastructures, better and worse in various ways, than the balanced
> binary tree..

I guess for no better reason than because no one has ever wanted it.
Actually, another reason may be because it is a rather large design
space and no one has been able to agree on what such a type class
might look like.  But don't let either of those stop you.  

-Brent


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

Message: 4
Date: Tue, 6 Jul 2010 11:06:53 +0100
From: Tom Hobbs <[email protected]>
Subject: Re: Fwd: [Haskell-beginners] More Deserialization Woes
To: Daniel Fischer <[email protected]>, [email protected]
Message-ID:
        <[email protected]>
Content-Type: text/plain; charset="iso-8859-1"

On Tue, Jul 6, 2010 at 10:42 AM, Daniel Fischer <[email protected]>wrote:

> Nevertheless, IO (Maybe [String]) is, I believe, the appropriate type.
>

I accept that you guys have most likely forgotten more about Haskell than I
know, but can you explain to me why this is the appropriate type?

Note to self: I think I've got the answer to this at the end of this email!


>
> >
> > However, the result of "IO [Just "a", Just "b", Nothing, Nothing]" would
> > signify that communication failed halfway through and would not make
> > sense in my context.  This is what the advice seems to be suggesting I
> > write.  But in this case, I'd prefer to return "Nothing" to signify that
> > a problem occurred.
>
> You can do that by applying sequence (at the type [Maybe String] -> Maybe
> [String]).
>
> Say you have
>
> ping0 :: args -> IO [Maybe String]
>
> then you'd use
>
> ping :: args -> IO (Maybe [String])
>  ping = fmap sequence ping0
>

Okay, I've looked at the definition of sequence in Prelude and I think I
understand what's going on.  I need to experiment with it first before I
fully get it.

So if ping0 returns IO [Just "a", Just "b", Nothing] then then what would
ping return?  IO (Just ["a", "b", ?]).  Nevermind, I can play with that and
work it out later.

Thinking to my requirement I think I'd want something more like;

ping :: args -> IO (Maybe [String])
ping args = fmap f ps
                 where
                 ps = ping0 args
                 f | Nothing `elem` ps = Nothing
                   | otherwise             = fmap sequence ps

Or would I get this behaviour for free straight from the use of sequence?


> >
> > Is it possible, to extract the values out of the IO monad so it can be
> > used in pure functions.
>
> Yes, but you needn't (and shouldn't in general).
>
>
Again, what is the why?

My theory is that I want to get [String] from ping, and then (possibly) do
lots of other things with it that don't require any kind of IO.  But maybe
that's not true and I need to think a bit harder about what the caller is
likely to do with the result from ping.  In terms of performance (memory
footprint, speed of execution, etc) does "carrying around the IO monad" make
much of a difference?

<insert five minute reflective pause here>

You're right.  I don't need to pull the [String] out of the IO monad.
 Suprise, suprise, the general pattern is appropriate in my case.  Something
clicked in my head when I re-read "pureStuff someValues" - this time is was
a good click though!

Please understand, I'm challenging you on the answers because I don't
understand them, not because I think they're wrong!  :-)

Thanks again for the very quick and helpful answers!

Tom



> The general pattern is
>
> main = do
>    someValues <- getDataIOAction
>    let otherValues = pureStuff someValues
>    outputIO otherValues
>
> >
> > For example, once ping has returned it's Maybe [IO String], I would like
> > to be able to create another function such as;
> >
> > purePing :: String -> PortNumber -> Maybe [String]
> > purePing a p = removeIOMonad (ping a p)
> >                       where
> >                       removeIOMonad Nothing = Nothing
> >                       removeIOMonad []    = Just []
> >                       removeIOMonad (x:xs)    = clevelDropIOMagic x :
> > removeIOMonad xs
> >
> > ...or something...
> >
> > Once the IO [String] has been read from the stream, no further IO is
> > necessary, so any other function should be able to just use the list and
> > not worry about the IO stuff.
> >
> > Again my questions are, Is this an okay thing to do, or is my
> > design/idea very, very wrong?
> >
> > Thanks again for the help,
> >
> > Tom
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
http://www.haskell.org/pipermail/beginners/attachments/20100706/baac6a92/attachment.html

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

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


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

Reply via email to