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: Randomness, lists, and unfoldr (Cook, James A CTR USA USMA)
2. Re: [Haskell-cafe] try, seq, and IO (Jeroen van Maanen)
3. Re: [Haskell-cafe] try, seq, and IO (Jeroen van Maanen)
4. Re: Capture stdout from a command on Windows (Christian Maeder)
5. Re: Padding List with Zeros (Henry Olders)
----------------------------------------------------------------------
Message: 1
Date: Tue, 14 Sep 2010 11:10:55 -0400
From: "Cook, James A CTR USA USMA" <[email protected]>
Subject: RE: [Haskell-beginners] Randomness, lists, and unfoldr
To: Daniel Fischer <[email protected]>, "[email protected]"
<[email protected]>
Message-ID:
<6757038bfdcd614da5213272d1e15798067a058...@usmasvgdoim522.usma.ds.army.edu>
Content-Type: text/plain; charset="us-ascii"
Daniel Fischer wrote:
> What you want would be something like
>
> iterateM :: (Monad m) => (a -> m a) -> a -> m [a]
> iterateM act start = do
> next <- act start
> rest <- iterateM act next
> return (start : rest)
>
> but that would only work if the bind is sufficiently lazy, otherwise you'd
> have to iterate a given number of times.
Daniel's explanation is exactly right - unfoldr doesn't work "in the monad",
and you need a function like this iterateM that does. Unfortunately (as he
hints) this exact function won't work because it tries to compute an infinite
list, which RVar can't do in finite time. Intstead, I would recommend starting
with a function such as iterateM and modifying it to accept a "number of steps"
parameter - effectively fusing the "take" step into the "unfoldr" step from
your original example - or to use some other knowledge of your algorithm to
limit the size of the list generated. For example, truncating the output when
the cell changes to False. That would be a bit silly in this example since
then your output would just be a variable-length list of "True"s, but I imagine
this is just a simplification of what you're really trying to accomplish anyway.
I'm pretty sure it would not be possible to make the bind lazy (even when the
remaining computation uses no entropy), because if nothing else the bind
operation would have to search the remaining (infinite) computation to make
sure it isn't going to require any more random sampling. Lazily sampling the
random variables wouldn't be an option either - that would effectively require
a generalized unsafeInterleaveIO which is somehow able to work in any monad,
since RVars can be run in all kinds of monads - State, IO, "ContT (FooT BarM)",
etc. - anything that has a 'RandomSource' or 'MonadRandom' instance.
Incidentally, the type of "unfoldr (\x -> Just (x, x >>= updateCell))" gives a
valuable clue about the behavior you can expect from it. Its type is [RVar
Bool], which is a list of random variables. Every RVar is (by design)
independent from all others, so that type just can't describe the operation you
want. "iterateM updateCell True" has the type you need, which is "RVar [Bool]".
-- James
------------------------------
Message: 2
Date: Thu, 16 Sep 2010 08:50:46 +0200
From: Jeroen van Maanen <[email protected]>
Subject: [Haskell-beginners] Re: [Haskell-cafe] try, seq, and IO
To: Neil Brown <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="iso-8859-1"
Op 2010-09-15 18:38, Neil Brown schreef:
> On 15/09/10 10:13, Jeroen van Maanen wrote:
>> The past year I have been working on a port of my machine learning project
>> named LExAu from Java to Haskell. I'm still very glad I took the jump,
>> because the complexity curve appears to be log shaped rather than exp
>> shaped. In one year I almost got to the functionality that had taken me five
>> years to produce in Java (of course it helped a lot that I had a working
>> prototype this time).
>>
>> There is one thing that still bothers me though: when I write seq or $! it
>> doesn't seem to have any effect!
>>
>> Currently I am trying to add some exception handling to help me debug the
>> system, but the code that I managed to produce depends on the logging
>> statement to produce the desired result. :-( It looks like this, and only
>> works when I uncomment the line '-- logger "Check sum": [...]', otherwise
>> the exception is caught by the try around the body of the thread that this
>> code runs in:
>>
>> do logger "Received update" [showString label, logs update]
>> result<-
>> try $!
>> do maybeUpdatedModel<- return $ f update startModel
>> theCheckSum<- return $ liftM checkSum maybeUpdatedModel
>> -- logger "Check sum" [showString label, shows theCheckSum]
>> return $! seq theCheckSum maybeUpdatedModel
>> maybeNextModel<-
>> case result of
>> Right theMaybeNextModel -> return theMaybeNextModel
>> Left exception ->
>> do let exc :: SomeException
>> exc = exception
>> logger "Exception" [showString label, shows exception]
>> return Nothing
>> logger "Maybe next model" [showString label, logs
>> maybeNextModel]
>>
>> For more context see:
>>
>>
>> http://lexau.svn.sourceforge.net/viewvc/lexau/branches/totem/src/LExAu/Pipeline/Concurrent.hs?revision=326&view=markup
>>
>> after line 241.
>>
>> Can someone explain why a few showStrings a shows and a putStrLn are more
>> effective in forcing the check sum to be computed (which necessarily
>> evaluates the complete updated model and reveals the lurking exception) than
>> the seq on the line just below the logging statement?
>>
> I just looked at your code for a second time and I think I know. Here's my
> guess:
>
> It's all about the types, and weak head normal form. The "theCheckSum" item
> has type Maybe a, and you are looking for an exception in the "a" part that's
> wrapped by Maybe (I presume: the Just/Nothing is determined by the function
> "f", not "checkSum"). When you use seq or $!, you only evaluated to weak
> head normal form, For something of type "Maybe a", that's only the
> Just/Nothing part. Forcing that aspect to be evaluated only requires some
> evaluation of the function "f", and the checkSum function doesn't need to be
> applied, even if it is a Just value. However, your shows function digs
> deeper and evaluates the whole thing, so hence it will trigger the error
> where seq and $! won't.
Ah, I didn't know that weak normal form evaluation doesn't force the evaluation
of the argument of the Just constructor. That makes sense. (I confess that I
added the liftM construction almost without thinking when the compiler told me
that I couldn't just ask for the checkSum of maybeUpdatedModel and had not
realized that this changed the type of theCheckSum. I also stubbornly ignored
the telltale "Just" in the log statement.)
> So, if I'm right, you need to change your function to make sure to evaluate
> the checksum itself. The deepseq package on Hackage may help here (use the
> deepseq function in place of seq:
> http://hackage.haskell.org/packages/archive/deepseq/1.1.0.0/doc/html/Control-DeepSeq.html).
The maybe function does the trick quite neatly. In fact, I added the checkSum
method because my particular data stuctures have quite natural Integer valued
functions that force evaluation of the complete, ... erm, in Java I would have
said object graph, ... you know, ... everything. ;-)
> I'm a little suspicious of the code as a whole though: why does checkSum
> throw an exception rather than returning a Maybe value? Or is it an
> exception somehow outside of your control?
That is because the exception is thrown by an assert kind of thing. There are
still bugs lurking in the code (strange, I have been so careful ;-> ), but I
don't want to litter my code with Maybe types just in case there Maybe
something wrong with it. I use Maybe frequently, for example, when a function
may or may not return an updated data structure when given some extra
information, but in those cases it is natural in the context of the algorithm
to use a Maybe type.
> Another thing:
>
> x <- return $ blah
>
> in a do block is bad style, and can always be replaced with:
>
> let x = blah
>
> Note that there is no "in" needed with let statements in do blocks (that
> confused me when first learning Haskell).
That's funny, first I fixed my code:
do let maybeUpdatedModel = f update startModel
theCheckSum <- return $ maybe 0 checkSum maybeUpdatedModel
return $! seq theCheckSum maybeUpdatedModel
That worked beautifully. The exception is caught here as desired. Then I tried
to get rid of the remaining '<- return'. However, when I write:
do let maybeUpdatedModel = f update startModel
theCheckSum = maybe 0 checkSum maybeUpdatedModel
return $! seq theCheckSum maybeUpdatedModel
It reverts to the old behavior. What is the subtle difference here?
And let me guess, the next step is to replace
do let blah
blah
return result
by
return $ let blah
blah
in result
Right?
Cheers, Jeroen
-------------- next part --------------
A non-text attachment was scrubbed...
Name: jeroen.vcf
Type: text/x-vcard
Size: 222 bytes
Desc: not available
Url :
http://www.haskell.org/pipermail/beginners/attachments/20100916/01c3bd4e/jeroen-0001.vcf
------------------------------
Message: 3
Date: Thu, 16 Sep 2010 10:54:33 +0200
From: Jeroen van Maanen <[email protected]>
Subject: [Haskell-beginners] Re: [Haskell-cafe] try, seq, and IO
To: Neil Brown <[email protected]>
Cc: [email protected], [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1
Op 2010-09-16 08:50, Jeroen van Maanen schreef:
> Op 2010-09-15 18:38, Neil Brown schreef:
>> On 15/09/10 10:13, Jeroen van Maanen wrote:
>>> The past year I have been working on a port of my machine learning project
>>> named LExAu from Java to Haskell. I'm still very glad I took the jump,
>>> because the complexity curve appears to be log shaped rather than exp
>>> shaped. In one year I almost got to the functionality that had taken me
>>> five years to produce in Java (of course it helped a lot that I had a
>>> working prototype this time).
>>>
>>> There is one thing that still bothers me though: when I write seq or $! it
>>> doesn't seem to have any effect!
>>>
>>> Currently I am trying to add some exception handling to help me debug the
>>> system, but the code that I managed to produce depends on the logging
>>> statement to produce the desired result. :-( It looks like this, and only
>>> works when I uncomment the line '-- logger "Check sum": [...]', otherwise
>>> the exception is caught by the try around the body of the thread that this
>>> code runs in:
>>>
>>> do logger "Received update" [showString label, logs update]
>>> result<-
>>> try $!
>>> do maybeUpdatedModel<- return $ f update startModel
>>> theCheckSum<- return $ liftM checkSum maybeUpdatedModel
>>> -- logger "Check sum" [showString label, shows
>>> theCheckSum]
>>> return $! seq theCheckSum maybeUpdatedModel
>>> maybeNextModel<-
>>> case result of
>>> Right theMaybeNextModel -> return theMaybeNextModel
>>> Left exception ->
>>> do let exc :: SomeException
>>> exc = exception
>>> logger "Exception" [showString label, shows exception]
>>> return Nothing
>>> logger "Maybe next model" [showString label, logs
>>> maybeNextModel]
>>>
>>> For more context see:
>>>
>>>
>>> http://lexau.svn.sourceforge.net/viewvc/lexau/branches/totem/src/LExAu/Pipeline/Concurrent.hs?revision=326&view=markup
>>>
>>> after line 241.
>>>
>>> Can someone explain why a few showStrings a shows and a putStrLn are more
>>> effective in forcing the check sum to be computed (which necessarily
>>> evaluates the complete updated model and reveals the lurking exception)
>>> than the seq on the line just below the logging statement?
>>>
>> I just looked at your code for a second time and I think I know. Here's my
>> guess:
>>
>> It's all about the types, and weak head normal form. The "theCheckSum" item
>> has type Maybe a, and you are looking for an exception in the "a" part
>> that's wrapped by Maybe (I presume: the Just/Nothing is determined by the
>> function "f", not "checkSum"). When you use seq or $!, you only evaluated
>> to weak head normal form, For something of type "Maybe a", that's only the
>> Just/Nothing part. Forcing that aspect to be evaluated only requires some
>> evaluation of the function "f", and the checkSum function doesn't need to be
>> applied, even if it is a Just value. However, your shows function digs
>> deeper and evaluates the whole thing, so hence it will trigger the error
>> where seq and $! won't.
>
> Ah, I didn't know that weak normal form evaluation doesn't force the
> evaluation of the argument of the Just constructor. That makes sense. (I
> confess that I added the liftM construction almost without thinking when the
> compiler told me that I couldn't just ask for the checkSum of
> maybeUpdatedModel and had not realized that this changed the type of
> theCheckSum. I also stubbornly ignored the telltale "Just" in the log
> statement.)
>
>> So, if I'm right, you need to change your function to make sure to evaluate
>> the checksum itself. The deepseq package on Hackage may help here (use the
>> deepseq function in place of seq:
>> http://hackage.haskell.org/packages/archive/deepseq/1.1.0.0/doc/html/Control-DeepSeq.html).
>
> The maybe function does the trick quite neatly. In fact, I added the checkSum
> method because my particular data stuctures have quite natural Integer valued
> functions that force evaluation of the complete, ... erm, in Java I would
> have said object graph, ... you know, ... everything. ;-)
>
>> I'm a little suspicious of the code as a whole though: why does checkSum
>> throw an exception rather than returning a Maybe value? Or is it an
>> exception somehow outside of your control?
>
> That is because the exception is thrown by an assert kind of thing. There are
> still bugs lurking in the code (strange, I have been so careful ;-> ), but I
> don't want to litter my code with Maybe types just in case there Maybe
> something wrong with it. I use Maybe frequently, for example, when a function
> may or may not return an updated data structure when given some extra
> information, but in those cases it is natural in the context of the algorithm
> to use a Maybe type.
>
>> Another thing:
>>
>> x <- return $ blah
>>
>> in a do block is bad style, and can always be replaced with:
>>
>> let x = blah
>>
>> Note that there is no "in" needed with let statements in do blocks (that
>> confused me when first learning Haskell).
>
> That's funny, first I fixed my code:
>
> do let maybeUpdatedModel = f update startModel
> theCheckSum <- return $ maybe 0 checkSum maybeUpdatedModel
> return $! seq theCheckSum maybeUpdatedModel
>
> That worked beautifully. The exception is caught here as desired. Then I
> tried to get rid of the remaining '<- return'. However, when I write:
>
> do let maybeUpdatedModel = f update startModel
> theCheckSum = maybe 0 checkSum maybeUpdatedModel
> return $! seq theCheckSum maybeUpdatedModel
>
> It reverts to the old behavior. What is the subtle difference here?
>
> And let me guess, the next step is to replace
>
> do let blah
> blah
> return result
>
> by
>
> return $ let blah
> blah
> in result
>
> Right?
Gregs suggestion provided the way out: evaluate. My code now looks like this:
do let maybeUpdatedModel = f update startModel
theCheckSum = maybe 0 checkSum maybeUpdatedModel
logException exception = logger "Exception" [showString label,
shows (exception :: SomeException)] >> return Nothing
logger "Received update" [showString label, logs update]
resultOrException <- try $ evaluate $ seq theCheckSum
maybeUpdatedModel
maybeNextModel <- either logException return resultOrException
logger "Maybe next model" [showString label, logs maybeNextModel]
-- ...
I still don't understand why evaluating maybeUpdatedModel to WHNF after seq
evaluated theCheckSum to WHNF forces the lurking exception to the surface. Or
is the phrase 'when the resultant IO action is executed' in the documentation
of 'evaluate' significant here?
Cheers, Jeroen
------------------------------
Message: 4
Date: Thu, 16 Sep 2010 13:55:24 +0200
From: Christian Maeder <[email protected]>
Subject: [Haskell-beginners] Re: Capture stdout from a command on
Windows
To: David Frey <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=UTF-8
Under Unix I use readProcess or readProcessWithExitCode from
System.Process to get the output without fiddling with handles.
HTH Christian
Am 15.09.2010 20:08, schrieb David Frey:
> Hi,
>
> I'm trying to capture the output (stdout) of a command on Windows.
>
> This is what I have so far:
>
> import System.Process (runProcess, waitForProcess)
> import System.IO (hGetContents)
>
> executeCapturingStdout :: String -> String -> IO [String]
> executeCapturingStdout cmd workingDir = do
> let stdoutHandle = -- TODO: What do I put here?
> processHandle <- runProcess cmd [] (Just workingDir) Nothing Nothing
> stdoutHandle Nothing
> exitCode <- waitForProcess processHandle
> content <- hGetContents stdoutHandle
> return lines content
>
> I have tried searching on google and I haven't been able to find an answer
> yet.
>
> Thanks,
> Dave
------------------------------
Message: 5
Date: Thu, 16 Sep 2010 12:32:00 -0400
From: Henry Olders <[email protected]>
Subject: Re: [Haskell-beginners] Padding List with Zeros
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii
On 2010-09-15, at 15:12 , Daniel Fischer wrote:
> On Wednesday 15 September 2010 20:24:09, Hein Hundal wrote:
>> On Wed, 15 Sep 2010 16:23:49, Daniel Fischer wrote:
>>> On Wednesday 15 September 2010 15:15:49, Henry Olders wrote:
>>>> On 2010-09-14, at 19:35 , Lorenzo Isella wrote:
>>>>> Dear All,
>>>>> I still have to find my way with immutable lists and list
>>>>> comprehension. Consider the following lists
>>>>>
>>>>> A=[0,10,20,30,40,50]
>>>>> B=[0,10,50] (i.e. B is a subset of list A; list A is
>>>>> already ordered in increasing order and so is B).
>>>>> C=[2,1,-5] i.e. there is a corresponding element in C for every
>>>>> element in B.
>>>>>
>>>>> Now, I would like to define a new list D having length equal
>>>>> to the length of A. The elements of D in the position of the
>>>>> elements of A in common with B are equal to the corresponding
>>>>> entries in C, whereas the other ones are zero i.e.
>>>>> D=[2,1,0,0,0,-5]. How can I achieve that? The first thought
>>>>> that comes to my mind is to define a list of zeros which I
>>>>> would modify according to my needs, but that is not allowed...
>>
>> Yes, that is not allowed. First thing I thought of also.
>>
>>>>> Many thanks
>>>>>
>>>>> Lorenzo
>>>>
>>>> Being a real Haskell newby, I can figure out a one-line solution in
>>>> Python, but I don't know how to do something similar in Haskell, or
>>>> even if it's possible. Please correct me if I'm wrong, but there
>>>> does not seem to be a dictionary type in Haskell, and I am not aware
>>>> of how to specify an inline if...else inside a list comprehension. I
>>>> would really appreciate it if someone could show me how to do
>>>> something similar to this Python statement in Haskell.
>>>
>>> import Data.Maybe
>>>
>>>>>>> A=[0,10,20,30,40,50]
>>>>>>> B=[0,10,50]
>>>>>>> C=[2,1,-5]
>>>
>>> These have to be lowercase in Haskell, of course :)
>>>
>>>>>>> [dict(zip(B,C))[a] if a in B else 0 for a in A]
>>>
>>> map (fromMaybe 0 . (`lookup` zip b c)) a
>>>
>>> or, as a list comprehension,
>>>
>>> [fromMaybe 0 (lookup v dic) | let dic = zip b c, v <- a]
>>>
>>> Slightly more verbose than the Python.
>>>
>>> But this doesn't deal with multiple entries (istr that was
>>> mentioned previously in this thread), for
>>>
>>> a = [0, 10, 10, 20, 30 , 40, 50]
>>> b = [0, 10, 10, 50]
>>> c = [2, 1, 3, -5]
>>>
>>> neither would produce
>>>
>>> [2, 1, 3, 0, 0, 0, -5]
>>>
>>> which I believe would be the desired behavior.
>>>
>>>> [2, 1, 0, 0, 0, -5]
>>>>
>>>> Henry
>>
>> I love the map solution and the lookup solutions--very concise. Someday
>> perhaps those will occur to me when I look at these problems.
>>
>> Here is my (extremely) verbose beginner solution. I think this solution
>> is linear time and it returns the "desired behavior" in Daniel's post.
>>
>> -- indices v1 v2
>> -- find the elemIndex of v2's elements in v1
>> -- almost equivalent to (map (flip elemIndex v1) v2)
>> --
>> indices v1 v2 = indices' 0 v1 v2
>> indices' iOff (x:xs) (y:ys)
>>
>> | x < y = indices' (iOff+1) xs (y:ys)
>> | x ==y = iOff:(indices' (iOff+1) xs ys)
>> | x > y = error "indicies:: elem not found"
>>
>> indices' _ _ [] = []
>> indices' _ [] (y:ys) = error "indices:: elem not found"
>>
>>
>> -- makevec 0 indices values
>> -- returns a vector with values filled in at the indices given
>> --
>> makevec _ [] _ = []
>> makevec _ _ [] = error "makevec:: "
>> makevec iOffSet (i:is) (x:xs)
>>
>> | iOffSet < i = replicate (i-iOffSet) 0 ++ makevec i (i:is) (x:xs)
>> | iOffSet ==i = x:(makevec (iOffSet+1) is xs)
>> | iOffSet > i = error "makevec error"
>>
>> hisfunc :: [Integer] -> [Integer] -> [Integer] -> [Integer]
>> hisfunc a b c = let front = makevec 0 (indices a b) c
>> in front ++ replicate (length a - length front) 0
>>
>>
>> test1 = hisfunc a b c
>> test2 = hisfunc (a++[70, 90]) b c
>> test3 = hisfunc (a++[70, 90]) (b++[70]) (c++[-14])
>> test4 = hisfunc [0,10,10,20,30,40,50] [0,10,10,50] [2,1,3,-5]
>
> Somewhat simpler in one go:
>
> -- Preconditions:
> -- length bs == length cs
> -- as and bs are sorted
> -- bs is a sublist of as
> expand :: (Ord a, Num a) => [a] -> [a] -> [a] -> [a]
> expand as [] _ = map (const 0) as
> expand (a:as) bbs@(b:bs) ccs@(c:cs)
> | a < b = 0 : expand as bbs ccs
> | otherwise = c : expand as bs cs
> expand _ _ _ = []
My thanks to the various contributors to this discussion. Lots of food for
thought!
Henry
------------------------------
_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners
End of Beginners Digest, Vol 27, Issue 38
*****************************************