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: Forcing evalation in the IO Monad (Philip Scott)
   2. Re:  Re: Forcing evalation in the IO Monad (Philip Scott)
   3. Re:  Re: Forcing evalation in the IO Monad
      (Stephen Blackheath [to Haskell-Beginners])
   4. Re:  Re: Forcing evalation in the IO Monad (Daniel Fischer)
   5. Re:  Re: Forcing evalation in the IO Monad (Daniel Fischer)
   6. Re:  Re: Forcing evalation in the IO Monad (Daniel Fischer)
   7. Re:  Re: Forcing evalation in the IO Monad
      (Stephen Blackheath [to Haskell-Beginners])
   8. Re:  calling polymorphic function in Selenium     question
      (Daniel Fischer)


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

Message: 1
Date: Fri, 16 Apr 2010 15:48:07 +0100
From: Philip Scott <[email protected]>
Subject: Re: [Haskell-beginners] Re: Forcing evalation in the IO Monad
To: Heinrich Apfelmus <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=UTF-8; format=flowed

Heinrich Apfelmus wrote:
> Philip Scott wrote:
>   
>> What I want is something like putStrLn that doesn't print anything, and
>> takes any type as its input, evaluates it to normal form and then does
>> nothing else. It might be called something like 'evaluate' have a type
>> like this
>>
>> evaluate :: a -> IO()
>>     
>
> With Hoogle, you can search for types:
>
>    http://haskell.org/hoogle/?hoogle=a+-%3E+IO+%28%29
>
> 12th result from the top.
>
>   
Genius indeed!

At least I had the right type, and even the right name.. :)

Thanks ever so much.

- Philip




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

Message: 2
Date: Fri, 16 Apr 2010 16:09:07 +0100
From: Philip Scott <[email protected]>
Subject: Re: [Haskell-beginners] Re: Forcing evalation in the IO Monad
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=UTF-8; format=flowed

Philip Scott wrote 
> The documentation says that, but it does appear to go deeper than just 
> one level:
>
> Debug.Trace Prelude Control.Exception> let a = trace "Hello" 42
> Debug.Trace Prelude Control.Exception> let b = trace "Frank" (a * 2)
> Debug.Trace Prelude Control.Exception> evaluate b
> Frank
> Hello
> 84
>
> Perhaps it specifies WHNF in case you 'evaluate' something which 
> doesn't have a HNF (like a partially applied function?).

It is actually quite interesting what it does in this case:

 > let f x = trace "jingle" (x * 2)
 > a <- evaluate (f)
 > :t f
f :: (Num a) => a -> a
 > :t a
a :: Integer -> Integer

So it does some sort of evaluation - it has decided we're going to be 
using Integers instead of Nums. I wonder what it is up to there.



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

Message: 3
Date: Sat, 17 Apr 2010 07:14:54 +1200
From: "Stephen Blackheath [to Haskell-Beginners]"
        <[email protected]>
Subject: Re: [Haskell-beginners] Re: Forcing evalation in the IO Monad
To: [email protected]
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=UTF-8

Philip Scott wrote:
> Daniel Fischer wrote:
>> Am Freitag 16 April 2010 16:25:08 schrieb Heinrich Apfelmus:
>>  
>>> Philip Scott wrote:
>>>    
>>>> What I want is something like putStrLn that doesn't print anything,
>>>> and takes any type as its input, evaluates it to normal form and then
>>>> does nothing else. It might be called something like 'evaluate' have a
>>>> type like this
>>>>
>>>> evaluate :: a -> IO()
>>>>       
>>> With Hoogle, you can search for types:
>>>
>>>    http://haskell.org/hoogle/?hoogle=a+-%3E+IO+%28%29
>>>
>>> 12th result from the top.
>>>     
>>
>> That evaluates only to WHNF.
>>
>> Control.DeepSeq.rnf seems to be closer, but requires NFData instances.
>>
>>   
> The documentation says that, but it does appear to go deeper than just
> one level:
> 
> Debug.Trace Prelude Control.Exception> let a = trace "Hello" 42
> Debug.Trace Prelude Control.Exception> let b = trace "Frank" (a * 2)
> Debug.Trace Prelude Control.Exception> evaluate b
> Frank
> Hello
> 84
> 
> Perhaps it specifies WHNF in case you 'evaluate' something which doesn't
> have a HNF (like a partially applied function?).

"evaluate x" is defined as "return $! x".  This indeed evaluates the
value immediately then and there.  It *only* evaluates to WHNF (weak
head normal form).  For number values, WHNF (= evaluate to outer
constructor only) and NF (= completely evaluate) are the same thing, as
shown in your example above.  The (a * 2) makes no difference, because
whether WHNF = NF or not depends on the type of the value only, not the
expression used to calculate it.

To evaluate x to NF (completely) then and there in general, you have to say

  evaluate (rnf x)

where rnf is defined in Control.DeepSeq in the 'deepseq' package.  The
type of x has to be an NFData instance.  Haskell does not provide any
other way to force evaluation to NF other than to explicitly use `seq`
on each element of the structure.  The purpose of DeepSeq is to make
this task easier.


Steve


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

Message: 4
Date: Fri, 16 Apr 2010 21:27:10 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Re: Forcing evalation in the IO Monad
To: [email protected]
Cc: Philip Scott <[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="utf-8"

Am Freitag 16 April 2010 17:09:07 schrieb Philip Scott:
> Philip Scott wrote
>
> > The documentation says that, but it does appear to go deeper than just
> > one level:
> >
> > Debug.Trace Prelude Control.Exception> let a = trace "Hello" 42
> > Debug.Trace Prelude Control.Exception> let b = trace "Frank" (a * 2)
> > Debug.Trace Prelude Control.Exception> evaluate b
> > Frank
> > Hello
> > 84
> >
> > Perhaps it specifies WHNF in case you 'evaluate' something which
> > doesn't have a HNF (like a partially applied function?).
>
> It is actually quite interesting what it does in this case:
>  > let f x = trace "jingle" (x * 2)
>  > a <- evaluate (f)
>  >
>  > :t f
>
> f :: (Num a) => a -> a
>
>  > :t a
>
> a :: Integer -> Integer
>
> So it does some sort of evaluation - it has decided we're going to be
> using Integers instead of Nums. I wonder what it is up to there.

Without impredicative polymorphism (whatever that is), you can't get a 
polymorphic value from an action, so while

Prelude Debug.Trace Control.Exception> :t evaluate f          
evaluate f :: (Num a) => IO (a -> a)

, when you bind the result of evaluate f to a name, that is assigned a 
monomorphic type. Without a type signature, the type variable a is 
defaulted to Integer. You can (until 6.14)
          
Prelude Debug.Trace Control.Exception> :set -XImpredicativeTypes
Prelude Debug.Trace Control.Exception> u <- evaluate f :: IO (forall a. Num 
a => a -> a)                                                                    
        

<no location info>:
    Warning: -XImpredicativeTypes is deprecated: impredicative polymorphism 
will be simplified or removed in GHC 6.14                                       
                  
Prelude Debug.Trace Control.Exception> :t u                                  
u :: (Num a) => a -> a                                                          
       
Prelude Debug.Trace Control.Exception> u 4 :: Int                            
jingle                                                                          
       
8                                                                               
       
Prelude Debug.Trace Control.Exception> u 4 :: Double
jingle                                                        
8.0                                                           
Prelude Debug.Trace Control.Exception> u 4 :: Rational
jingle                                                          
8 % 1


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

Message: 5
Date: Fri, 16 Apr 2010 21:41:56 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Re: Forcing evalation in the IO Monad
To: Philip Scott <[email protected]>, [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="utf-8"

Am Freitag 16 April 2010 20:50:21 schrieb Philip Scott:
> > Prelude Control.Exception>  let lst = [undefined,undefined] :: [Bool]
> > Prelude Control.Exception>  evaluate lst>>= putStrLn . take 1 . show
> > [
> > Prelude Control.Exception>  evaluate lst>>= print
> > [*** Exception: Prelude.undefined
>
> Ahh, yes you are of course right. Hmm so, how do we crack this nut
> without resorting to deepSeq etc.. It must be possible, because it
> happens when you print it!

When you print it, show demands that the value be completely evaluated. If 
the data-dependencies require an expression to be completely evaluated, it 
will be done. And that's basically the only way to get expressions 
evaluated. 'seq' and its relatives only give you a means to introduce new 
(artificial) data-dependencies.

>
> Am I going to have to resort to physically writing the output to
> /dev/null ?

I think deepseq/rnf from Control.DeepSeq and NFData instances may be easier 
than writing stuff to /dev/null.

>
> It seems like such an ordinary thing to want to do,

Not really. Wanting something to be completely evaluated without a direct 
need from data-dependencies is something not too ordinary in a lazy 
language. Of course, you sometimes need it, that's why there are seq and 
NFData. But it remains something special.

> the fact that it is
> hard makes me think I must be approaching this in the wrong way (which
> is usually the case when I get my knickers in a twist with Haskell ;)
>
> - Phil



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

Message: 6
Date: Fri, 16 Apr 2010 21:47:57 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Re: Forcing evalation in the IO Monad
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="utf-8"

Am Freitag 16 April 2010 21:14:54 schrieb Stephen Blackheath [to Haskell-
Beginners]:
>
> "evaluate x" is defined as "return $! x". 

Not quite:

Prelude Control.Exception> evaluate (undefined :: Int) `seq` True
True
Prelude Control.Exception> ((return $! undefined) :: IO Int) `seq` True
*** Exception: Prelude.undefined

Haddocks:

"Forces its argument to be evaluated to weak head normal form when the 
resultant IO  action is executed. It can be used to order evaluation with 
respect to other IO  operations; its semantics are given by

   evaluate x `seq` y    ==>  y
   evaluate x `catch` f  ==>  (return $! x) `catch` f
   evaluate x >>= f      ==>  (return $! x) >>= f

Note: the first equation implies that (evaluate x) is not the same as 
(return $! x). A correct definition is

   evaluate x = (return $! x) >>= return
"

> This indeed evaluates the
> value immediately then and there.  It *only* evaluates to WHNF (weak
> head normal form).  For number values, WHNF (= evaluate to outer
> constructor only) and NF (= completely evaluate) are the same thing, as
> shown in your example above.  The (a * 2) makes no difference, because
> whether WHNF = NF or not depends on the type of the value only, not the
> expression used to calculate it.
>
> To evaluate x to NF (completely) then and there in general, you have to
> say
>
>   evaluate (rnf x)
>
> where rnf is defined in Control.DeepSeq in the 'deepseq' package.  The
> type of x has to be an NFData instance.  Haskell does not provide any
> other way to force evaluation to NF other than to explicitly use `seq`
> on each element of the structure.  The purpose of DeepSeq is to make
> this task easier.
>
>
> Steve


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

Message: 7
Date: Sat, 17 Apr 2010 08:22:47 +1200
From: "Stephen Blackheath [to Haskell-Beginners]"
        <[email protected]>
Subject: Re: [Haskell-beginners] Re: Forcing evalation in the IO Monad
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=UTF-8

All,

Philip's original question was:
> This question is so trivial it must have been answered before, but I
> have been googling all morning to no avail so please bear with me. I've
> been wading through mires of $! and seq, deepSeq, $!! etc.. and I have
> leaned a lot of useful stuff about lazy evaluation - but I haven't been
> able to solve my problem.. What I would like to do is to force an
> expression to be fully evaluated to normal form, from inside the IO
> monad, right there and then.
>
> For example, in GHCI, calling putStrLn does just what I want:
>
> Debug.Trace Prelude> let a = trace "Hello" 42
> Debug.Trace Prelude> putStrLn $ show a
> Hello
> 42
>
> Except that it only takes showable things, and it puts an annoying
> message on the screen.

Daniel - I get what you're saying...

Daniel Fischer wrote:
> Am Freitag 16 April 2010 21:14:54 schrieb Stephen Blackheath [to Haskell-
> Beginners]:
>> "evaluate x" is defined as "return $! x".
>
> Not quite:
>
> Prelude Control.Exception> evaluate (undefined :: Int) `seq` True
> True
> Prelude Control.Exception> ((return $! undefined) :: IO Int) `seq` True
> *** Exception: Prelude.undefined

I'll explain the difference for the benefit of beginners:

For IO actions that take arguments, there are two steps involved in
executing them in IO:
1. evaluate it to value of type "IO a", and
2. sequence it, which is a general monad term, but in the IO monad it
means that it will be actually executed.

IO actions that don't take arguments, like getLine, just go straight to
step 2.

For example, if you have 'putStrLn name', then

1. Evaluate:  Apply the argument name (type: String) to putStrLn (type:
String -> IO ()).  This gives a value of type IO ().  This is plain old
ordinary pure Haskell function evaluation.
2. Sequence:  The action embodied in the IO () value is actually
executed, and the name appears on the screen.

The difference between the two ways of forcing evaluation are, therefore:

"return $! x" does the forcing when it is evaluated.

"evaluate x" does the forcing when it is sequenced.

Since sequencing demands evaluation anyway, in all practical situations
these are equivalent.  But "evaluate x" works more like what you would
expect:  "evaluate (rnf x)" is exactly analogous to "putStrLn (show x)"
except without the screen output.


Steve


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

Message: 8
Date: Fri, 16 Apr 2010 22:48:05 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] calling polymorphic function in
        Selenium        question
To: [email protected]
Cc: MH <[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain;  charset="iso-8859-1"

Am Montag 05 April 2010 03:25:16 schrieb MH:
> I am running the following code that is using Selenium. If you look at
> the function "start", you will see that the return type of the
> function is polymorphic.

Actually the return type is monomorphic, but the returned value can be 
something of type

Selenium a -> IO (Either String a)

for whichever monomorphic type a the caller wants.
Explicitly,

start :: forall a. String -> IO (Selenium a -> IO (Either String a))

What you seem to want would be

start :: String -> IO (forall a. Selenium a -> IO (Either String a))

That requires {-# LANGUAGE ImpredicativeTypes #-}, which is deprecated (and 
will be removed or drastically changed in 6.14).

> Now in main function, I call start function
> to get selenium IO monad and sequentially call selenium commands
> (open, doCommand etc...). The problem that I have here is, while I can
> call all Selenium commands with signature (String  -> Selenium
> String), I can't call commands with signature (String  -> Selenium
> Bool). As I understand it, even though "start" function shall return
> IO (Selenium a -> IO (Either String a)), it actually return IO
> (Selenium String -> IO (Either String String)).
> How shall go about fixing this problem?
> I need to be able to call both types of Selenium commands
> 1. doCommand :: SCommand  -> [String] -> Selenium  String
> OR
>    selectFrame :: String  -> Selenium  String
>
> AND
> 2. isTextPresent :: String  -> Selenium  Bool
>
>
> Thanks.
> =========================================================
{-# LANGUAGE ImpredicativeTypes #-}
> module SeleniumTest where
> import Control.Monad.Error
> import Data.Maybe
> import Network.BSD
> import Network.URI
>
> import Test.Selenium.Server
> import Test.Selenium.Syntax
> infixr 0 $$
>
> -- | Starts up a session and returns a wrapper function that will run
> --   commands. Gives common defaults for browser and host.
start :: String -> IO (forall a. Selenium a -> IO (Either String a))
> start url = do
> --  host <- getHostName
>   start' Firefox "localhost" url
>
> -- | Starts up a session and returns a wrapper function that will run
> --   commands.
start' :: Browser -> HostName -> String
        -> IO (forall a. Selenium a -> IO (Either String a))
> start' browser host url = do
>   let uri = fromJust (parseURI url)
>       sel = mkSeleniumRCSession host browser uri
>   result <- runSelenium sel startSelenium
    return (runSelenium (either (\msg -> error msg) id result)
>
>
> ($$) :: Show t => (Selenium () -> r)
>      -> Selenium t -> r
> ($$) s c = s $ do r <- c; liftIO (putStrLn $ "Result: " ++ show r);
> return ()
>
> -- | Stops a session (in the wrapper returned by start)
> stop :: Selenium ()
> stop = stopSelenium
>
> --main::IO()
> main = do
>     selenium <- start "http://www.google.com";
>     selenium $ open "/"
>     selenium $ doCommand SWindowMaximize []
>     selenium $ typeText (Name "q") "stuff"
>     selenium $ clickAndWait (Name "btnG")
>     return selenium
>
> ===============================================================

compiles and might do what you want.

But I think it's meant to be used differently, more like

selenium :: Selenium String    -- or Bool, whathaveyou
selenium = do
    open "/"
    doCommand SWindowMaximize []
    typeText (Name "q") "stuff"
    clickAndWait (Name "btnG")

use url = do
    let uri = fromJust (parseURI url)
        sel = mkSeleniumRCSession host browser uri
    runSelenium sel selenium

main = use "http://www.google.com";

Compose the Selenium actions and call the composed action from main.


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

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


End of Beginners Digest, Vol 22, Issue 26
*****************************************

Reply via email to