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. example of compostion (Rainer Grimm)
2. Re: Any advice on installing gtk2hs (patricklynch)
3. Re: example of compostion (Ozgur Akgun)
4. Re: Any advice on installing gtk2hs (Daniel Fischer)
5. Re: Any advice on installing gtk2hs (Krzysztof Skrz?tnicki)
6. Almost there. Bizzaro problem with libcurl forces kludge
that I would like to be rid of. (Michael Litchard)
----------------------------------------------------------------------
Message: 1
Date: Mon, 31 Jan 2011 22:15:18 +0100
From: Rainer Grimm <[email protected]>
Subject: [Haskell-beginners] example of compostion
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="iso-8859-15"
Hello,
I'm looking for a good example of function composition. It's very
impressive, how concise you can extract information out of a file in
Haskell. So I write a short programm, which gets all title words out of
a given file sorted by their length.
How could the following programm be improved?
import Data.Char (isUpper,isLower)
import Data.List (sortBy)
import Data.Ord (comparing)
isTitle word=
isFirstUpperCase ( word) && isTailLowerCase ( word )
where isFirstUpperCase= isUpper . head
isTailLowerCase= all isLower . tail
main = do
putStrLn "The name of the input file:"
file <- getLine
inputString <- readFile file
let allTitles= reverse . sortBy (comparing length ) . filter isTitle $
words inputString
putStrLn $ show $ take 15 allTitles
putStrLn $ show (length allTitles) ++ " titles in " ++ file
Thanks in advance,
Rainer
--
Rainer Grimm [email protected]
http://www.grimm-jaud.de
<javascript:void(0);>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20110131/e3df3b8d/attachment-0001.htm>
------------------------------
Message: 2
Date: Mon, 31 Jan 2011 17:25:08 -0500
From: "patricklynch" <[email protected]>
Subject: Re: [Haskell-beginners] Any advice on installing gtk2hs
To: <[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain; charset="us-ascii"
To Aditya Siram
...thanks for writing the procedure in the link in the email below......
...I got stuck on the command: 'cabal install gtk'
...it gives the following message:
Linking:
C:\Users\User\AppData\Local\cairo-0.12.043\cairo-0.12\dist\setup\setup.exe
...
Cannot find gtk2hsC2hs
Please install 'gtk2hs-buildtools' first and check that the install
Directory is in your PATH (e.g.. HOME/.cabal/bin)
My PATH is C:/Users/User/AppData/Roaming/cabal/bin
Should I change my PATH?
Good day
-----Original Message-----
From: patricklynch [mailto:[email protected]]
Sent: Monday, January 31, 2011 1:55 PM
To: 'patricklynch'; [email protected]
Subject: RE: Any advice on installing gtk2hs
PS, this was for the Windows installation...
-----Original Message-----
From: patricklynch [mailto:[email protected]]
Sent: Monday, January 31, 2011 1:54 PM
To: '[email protected]'
Subject: Any advice on installing gtk2hs
Good afternoon,
Any advice on installing gtk2hs...
I used the instructions at: http://www.haskell.org/haskellwiki/Gtk2Hs and
get a bunch of error messages...
Thanks...
-------------- next part --------------
A non-text attachment was scrubbed...
Name: winmail.dat
Type: application/ms-tnef
Size: 6144 bytes
Desc: not available
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20110131/3c9b09d6/attachment-0001.bin>
------------------------------
Message: 3
Date: Mon, 31 Jan 2011 22:04:59 +0000
From: Ozgur Akgun <[email protected]>
Subject: Re: [Haskell-beginners] example of compostion
To: Rainer Grimm <[email protected]>
Cc: [email protected]
Message-ID:
<[email protected]>
Content-Type: text/plain; charset="utf-8"
On 31 January 2011 21:15, Rainer Grimm <[email protected]> wrote:
> isTitle word=
> isFirstUpperCase ( word) && isTailLowerCase ( word )
> where isFirstUpperCase= isUpper . head
> isTailLowerCase= all isLower . tail
>
One possible improvement is using pattern matching while defining isTitle.
isTitle [] = False -- I suppose?
isTitle (x:xs) = isUpper x && all isLower xs
--
Ozgur
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20110131/22056b24/attachment-0001.htm>
------------------------------
Message: 4
Date: Mon, 31 Jan 2011 23:11:50 +0100
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Any advice on installing gtk2hs
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="utf-8"
On Monday 31 January 2011 23:25:08, patricklynch wrote:
> To Aditya Siram
>
>
>
> ...thanks for writing the procedure in the link in the email below......
>
> ...I got stuck on the command: 'cabal install gtk'
>
> ...it gives the following message:
>
>
>
> Linking:
>
> C:\Users\User\AppData\Local\cairo-0.12.043\cairo-0.12\dist\setup\setup.e
>xe
>
> ...
>
> Cannot find gtk2hsC2hs
>
> Please install 'gtk2hs-buildtools' first and check that the install
>
> Directory is in your PATH (e.g.. HOME/.cabal/bin)
>
Have you done 'cabal install gtk2hs-buildtools' first?
That step is not listed under point 5.1.5, that may be an oversight.
If you have, where is gtk2hsC2hs located, is it in
C:/Users/User/AppData/Roaming/cabal/bin or elsewhere?
>
>
> My PATH is C:/Users/User/AppData/Roaming/cabal/bin
>
> Should I change my PATH?
>
>
>
> Good day
>
>
------------------------------
Message: 5
Date: Mon, 31 Jan 2011 23:05:33 +0100
From: Krzysztof Skrz?tnicki <[email protected]>
Subject: Re: [Haskell-beginners] Any advice on installing gtk2hs
To: patricklynch <[email protected]>
Cc: [email protected]
Message-ID:
<[email protected]>
Content-Type: text/plain; charset="utf-8"
>
>
> Cannot find gtk2hsC2hs
>
> Please install 'gtk2hs-buildtools' first and check that the install
>
> Well, did you follow the message with 'cabal install gtk2hs-buildtools'
then?
Best regards,
Krzysztof Skrz?tnicki
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20110131/8e30b64b/attachment-0001.htm>
------------------------------
Message: 6
Date: Mon, 31 Jan 2011 14:42:30 -0800
From: Michael Litchard <[email protected]>
Subject: [Haskell-beginners] Almost there. Bizzaro problem with
libcurl forces kludge that I would like to be rid of.
To: [email protected]
Message-ID:
<[email protected]>
Content-Type: text/plain; charset="iso-8859-1"
So, I've been writing a http client designed to simulate a session with one
of my company's products.
The crucial thing we need from this program is a cookie jar. When I began I
was doing exploratory code to figure things out about http. I managed to
make a cookie jar with my toy code, along with the intermediate steps needed
to generate the cookies that represent a session.
Then it was time to integrate my experimental toy code into something closer
to what production code should look like.
This is where bizarro behavior starts to happen. All the intermediate steps
appear to be working, as later steps are dependent on earlier steps
succeeding. Yet in the end, no cookie jar.
We did an strace on the binary and it appears that there seems to be a
problem with the reading/writing of the file to be the cookie jar, and we
don't know why. The kludge solution is to write a wrapper that calls the
program in such a way that I can capture standard error and parse out the
cookies. I would hate for things to remain this way. It disturbs me.
So, my toy code can create a cookie jar. But what will one day be production
code does everything correctly except produce the cookie jar. Included is
the entire program, standard error, and strace output. Also, my toy program
which succeeds in producing a cookie jar. If anyone wants to take a stab at
this that would be peachy. I'm looking for avenues to explore and good
questions to ask, as I am out of both.
P.S. Thanks to everyone who got me this far. If this is what we end up
having to use, it does get the job done. I'm just trying to get rid of my
kludge work-around.
> {-# LANGUAGE FlexibleContexts #-}
> module Main where
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
> import Control.Monad
> import Control.Monad.Error
> import Network.Curl
> import System.Environment (getArgs)
> import HtmlParsing
> import SessionCreator
> main :: IO ()
> main = do
> curl <- initCurl
> user:pass:_ <- getArgs
> resp <- generateResourceHtml curl user pass
>
> case resp of
> Left err -> print err
> Right body -> obtainCookies curl body
> {-# LANGUAGE FlexibleContexts #-}
> module SessionCreator
> (
> initCurl,
> curlResp,
> urlBase,
> urlInitial,
> urlLogin,
> urlLogOut,
> urlFlash1,
> urlFlash2,
> urlLaunch,
> urlLaunchTest,
> urlQuickCreate,
> urlGetResource,
> urlShowWebForwards,
> respBody,
> -- login
> resourceOpts,
> loginOpts
> ) where
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
--import qualified Data.ByteString as B
> import Network.Curl
> import Control.Monad
> import Control.Monad.Error
> initCurl :: IO Curl
> initCurl = do
> curl <- initialize
> setopts curl curlOpts
> return curl
> curlOpts :: [CurlOption]
> curlOpts =
> [ CurlCookieSession True
> , CurlCookieJar "cookies.txt"
> , CurlCookieFile "cookies2.txt"
> , CurlFollowLocation True
> , CurlUserAgent "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"
> , CurlVerbose True
> , CurlHeader True
> , CurlAutoReferer True
> , CurlFailOnError True
> ]
> --- loginOpts looks like this for now
> loginOpts :: String -> String -> [CurlOption]
> loginOpts user pass =
> [ CurlFailOnError True
> , CurlPost True
> , CurlNoBody False
> , CurlPostFields
> [ "_charset_=UTF-8"
> , "javaScript=true"
> , "username=" ++ user
> , "password=" ++ pass
> ]
> ]
> resourceOpts :: [CurlOption]
> resourceOpts =
> [ CurlHttpHeaders
> [ "Accept: text/javascript, text/html, application/xml, text/xml, */*"
> , "Accept-Language: en-us,en;q=0.5"
> , "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7"
> , "Keep-Alive: 115"
> , "Connection: keep-alive"
> , "X-Requested-With: XMLHttpRequest"
> , "X-Prototype-Version: 1.6.0.3"
> ]
> , CurlEncoding "gzip,deflate"
> ]
> curlResp :: (Error e, MonadError e m, MonadIO m) =>
> Curl -> URLString -> [CurlOption] -> m String --CurlResponse
> curlResp curl url opts = do
> resp <- liftIO $ (do_curl_ curl url opts :: IO CurlResponse)
> let code = respCurlCode resp
> status = respStatus resp
> if code /= CurlOK || status /= 200
> then throwError $ strMsg $ "Error: " ++ show code ++ " -- " ++ show
status
> else return $ respBody resp
------------------------------------------------------------------------------
URLs
------------------------------------------------------------------------------
> (//) :: String -> String -> String
> a // b = a ++ "/" ++ b
> urlBase :: URLString
> urlBase = "https://172.16.1.18"
> urlInitial = urlBase // "showLogon.do"
> urlLogin = urlBase // "default/showLogon.do"
> urlFlash1 = urlBase // "showFlashCheck.do"
> urlFlash2 = urlBase // "logon.do?flashVersion=10.1.102"
> urlShowWebForwards = urlBase // "showWebForwards.do"
> urlGetResource = urlBase //
"resourceList.do?form=webForwardsForm&readOnly=false&policyLaunching=true&resourcePrefix=webForwards&path=%2FshowWebForwards.do&messageResourcesKey=webForwards&actionPath=%2FresourceList.do"
> urlCreateWebForward = urlBase //
"quickCreateWebForward.do?actionTarget=create&actionPath=%2FquickCreateWebForward.do%3FactionTarget%3Dcreate&quickCreate=true&evalJS=true&evalScripts=true"
> urlLogOut = urlBase // "logoff.do"
> urlQuickCreate = urlBase //
"quickCreateWebForward.do?actionTarget=create&actionPath=%2FquickCreateWebForward.do%3FactionTarget%3Dcreate&quickCreate=true&evalJS=true&evalScripts=true"
> module HtmlParsing
> (
> obtainCookies
> ,generateResourceHtml
> ) where
> import Text.HTML.TagSoup
> import Data.List.Split
> import Data.List
> import Data.Maybe
> import Numeric
> import Network.Curl
> import Control.Monad
> import Control.Monad.Error
> import SessionCreator
> processHTML :: String -> [[String]]
> processHTML htmlFILE =
> let parsedHTML = parseTags htmlFILE
> allTagOpens = sections (~== TagOpen "a"
[("href","")]) parsedHTML
> taggedTEXT = head $ map (filter isTagOpen)
allTagOpens
> allHREFS = map (fromAttrib "href") taggedTEXT
> allPotentials = map (dropWhile (/= '?')) allHREFS
> removedNulls = filter (not . null) allPotentials
> removedQs = map (drop 1) removedNulls
> in map (splitOn "&") removedQs
> createIDList :: [[String]] -> [String]
> createIDList strungPairs =
> let nvList = map (map (splitOn "=")) strungPairs
> nvTuple = map (map (list2Tuple)) nvList
> netofResources = map (lookup "resourceId") nvTuple
> removedNothings = catMaybes netofResources
> sortedIds = (map head . group . sort) $ map (\x -> read x
:: Int) removedNothings
> in map ("ResourceId" %%) $ map show sortedIds
> list2Tuple :: [a] -> (a,a)
> list2Tuple [x,y] = (x,y)
> (%%) :: String -> String -> String
> a %% b = a ++ "=" ++ b
> generateResourceHtml :: Curl -> String -> String -> IO (Either String
String)
> generateResourceHtml curl user pass = do
> let makeIDPage = do
> curlResp curl urlInitial method_GET
> curlResp curl urlLogin $ loginOpts user pass
> curlResp curl urlFlash1 resourceOpts
> curlResp curl urlFlash2 resourceOpts
> curlResp curl urlShowWebForwards resourceOpts
> curlResp curl urlQuickCreate resourceOpts
> curlResp curl urlGetResource resourceOpts
> runErrorT makeIDPage
> obtainCookies :: Curl -> String -> IO ()
> obtainCookies curl responseBody = do
> mapM_ (flip (curlResp curl) resourceOpts) $
> screenScraping responseBody
> screenScraping :: String -> [String]
> screenScraping responseBody =
> let collectedStrings = processHTML responseBody
> collectedIDLists = createIDList collectedStrings
> in constructedResourceURIs urlBase collectedIDLists
> constructedResourceURIs :: String -> [String] -> [String]
> constructedResourceURIs url resourceIDs =
> let frontURI = url ++ "/launchWebForward.do?"
> midURI = map (frontURI ++) resourceIDs
> in map (++
"&policy=0&returnTo=%2FshowWebForwards.do") midURI
Here is the toy (produces a cookiejar) program.
Attached are all the output files
{-# LANGUAGE FlexibleContexts #-}
module Main where
------------------------------------------------------------------------------
-- Imports
------------------------------------------------------------------------------
import Control.Monad
import Control.Monad.Error
import Network.Curl
import System.Environment (getArgs)
------------------------------------------------------------------------------
-- Curl
------------------------------------------------------------------------------
initCurl :: IO Curl
initCurl = do
curl <- initialize
setopts curl curlOpts
return curl
curlOpts :: [CurlOption]
curlOpts =
[ CurlCookieSession True
, CurlCookieJar "cookies.txt"
, CurlCookieFile "cookies.txt"
, CurlFollowLocation True
, CurlUserAgent "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"
, CurlVerbose True
]
loginOpts :: String -> String -> [CurlOption]
loginOpts user pass =
[ CurlFailOnError True
, CurlPost True
, CurlNoBody False
, CurlPostFields
[ "_charset_=UTF-8"
, "javaScript=true"
, "username=" ++ user
, "password=" ++ pass
]
]
curlResp
:: (MonadError String m, MonadIO m)
=> Curl -> URLString -> [CurlOption] -> m String --CurlResponse
curlResp curl url opts = do
resp <- liftIO $ (do_curl_ curl url opts :: IO CurlResponse)
let code = respCurlCode resp
status = respStatus resp
if code /= CurlOK || status /= 200
then throwError $ "Error: " ++ show code ++ " -- " ++ show status
else return $ respBody resp
------------------------------------------------------------------------------
-- URLs
------------------------------------------------------------------------------
(//) :: String -> String -> String
a // b = a ++ "/" ++ b
urlBase :: URLString
urlBase = "https://172.16.1.18"
urlInitial = urlBase // "showLogon.do"
urlLogin = urlBase // "default/showLogon.do"
urlFlash1 = urlBase // "showFlashCheck.do"
urlFlash2 = urlBase // "logon.do?flashVersion=9.0.100"
urlLaunch = urlBase //
"launchWebForward.do?resourceId=4&policy=0&returnTo=%2FshowWebForwards.do"
urlLaunchTest = urlBase //
"launchWebForward.do?resourceId=5&policy=0&returnTo=%2FshowWebForwards.do"
curlResp
:: (MonadError String m, MonadIO m)
=> Curl -> URLString -> [CurlOption] -> m String --CurlResponse
curlResp curl url opts = do
resp <- liftIO $ (do_curl_ curl url opts :: IO CurlResponse)
let code = respCurlCode resp
status = respStatus resp
if code /= CurlOK || status /= 200
then throwError $ "Error: " ++ show code ++ " -- " ++ show status
else return $ respBody resp
------------------------------------------------------------------------------
-- URLs
------------------------------------------------------------------------------
(//) :: String -> String -> String
a // b = a ++ "/" ++ b
urlBase :: URLString
urlBase = "https://172.16.1.18"
urlInitial = urlBase // "showLogon.do"
urlLogin = urlBase // "default/showLogon.do"
urlFlash1 = urlBase // "showFlashCheck.do"
urlFlash2 = urlBase // "logon.do?flashVersion=9.0.100"
urlLaunch = urlBase //
"launchWebForward.do?resourceId=4&policy=0&returnTo=%2FshowWebForwards.do"
urlLaunchTest = urlBase //
"launchWebForward.do?resourceId=5&policy=0&returnTo=%2FshowWebForwards.do"
------------------------------------------------------------------------------
-- IO
------------------------------------------------------------------------------
launch :: String -> String -> IO (Either String String)
launch user pass = do
-- Initialize Curl
curl <- initCurl
-- Sequence of steps
let steps = do
curlResp curl urlInitial method_GET
curlResp curl urlLogin $ loginOpts user pass
curlResp curl urlFlash1 method_GET
curlResp curl urlFlash2 method_GET
curlResp curl urlLaunch method_GET
-- curlResp curl urlLaunchTest method_GET
-- You'd use this to catch the exception right away
-- `catchError` \e-> ...
runErrorT steps
main :: IO ()
main = do
-- username and password
user:pass:_ <- getArgs
-- Launch webpage
resp <- launch user pass
-- Response comes as Either String String
-- You have to handle each case
case resp of
Left err -> print err
Right body -> putStrLn body
So to sum up again, I'm trying to figure out why the toy program generates a
cookie jar and the other program does everything it should *except* produce
a cookie jar. Thanks to anyone who wants to slog through this.
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20110131/5d5cd349/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: production_headers
Type: application/octet-stream
Size: 57684 bytes
Desc: not available
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20110131/5d5cd349/attachment.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: production_log
Type: application/octet-stream
Size: 1565292 bytes
Desc: not available
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20110131/5d5cd349/attachment-0001.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: toy_headers
Type: application/octet-stream
Size: 24335 bytes
Desc: not available
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20110131/5d5cd349/attachment-0002.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: toy_strace
Type: application/octet-stream
Size: 713169 bytes
Desc: not available
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20110131/5d5cd349/attachment-0003.obj>
------------------------------
_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners
End of Beginners Digest, Vol 31, Issue 40
*****************************************