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:  "Learn You a Haskell" question (Frank)
   2. Re:  Data.Stream interleave implementation question
      (Frerich Raabe)
   3. Re:  Disappointing thought on Haskell -- a simple space leak
      on "insert" is hard bug to catch (Dimitri DeFigueiredo)
   4. Re:  Using Traversal as a kind of pointer (Elise Huard)


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

Message: 1
Date: Mon, 18 Aug 2014 16:28:19 -0400
From: Frank <[email protected]>
To: The Haskell-Beginners Mailing List - Discussion of primarily
        beginner-level topics related to Haskell <[email protected]>
Subject: Re: [Haskell-beginners] "Learn You a Haskell" question
Message-ID:
        <ca+a3wkjn0zxca1f61cj8hvje43ummacij-ydjacak2tzjof...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"

Thanks!

On Monday, August 18, 2014, Bob Ippolito <[email protected]> wrote:

> The definition of a Functor requires that exactly one of the type
> variables be free, which is why it's written as `Either a` instead of
> `Either a b`. Any fields that are not `b` must be simply passed through
> as-is by fmap. There could be a separate functor that would fmap over the
> Left, but there isn't (in the base package anyhow).
>
> There's a related Functor for `(,) a` where the Functor fmaps over the snd
> of the tuple, and the fst is left as-is.
>
> fmap (+1) ('a', 2) == ('a', 3)
> fmap (+1) (Right 2) == Right 3
> fmap (+1) (Left 'a') == Left 'a'
>
> Chris Done recently prototyped a fmap explorer that you might find useful:
> http://www.reddit.com/r/haskell/comments/2dok9w/functor_explorer/
>
> -bob
>
>
>
> On Mon, Aug 18, 2014 at 11:02 AM, Frank <[email protected]
> <javascript:_e(%7B%7D,'cvml','[email protected]');>> wrote:
>
>> Hi,
>>     I'm reading "Learn You a Haskell..." and have a question about the
>> chapter "Making Our Own Types and Typeclasses". On the 'Functor'/'Either'
>> example, I feel completely lost. I don't see why the 'Left x' portion of
>> 'Functor (Either a)' is simply 'Left x' and the document is not exactly
>> clear. Any clarification would be most appreciated.
>>
>> Sincerely,
>> Frank D. Martinez
>>
>>
>> --
>> P.S.: I prefer to be reached on BitMessage at
>> BM-2D8txNiU7b84d2tgqvJQdgBog6A69oDAx6
>>
>> _______________________________________________
>> Beginners mailing list
>> [email protected]
>> <javascript:_e(%7B%7D,'cvml','[email protected]');>
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>>
>

-- 
P.S.: I prefer to be reached on BitMessage at
BM-2D8txNiU7b84d2tgqvJQdgBog6A69oDAx6
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20140818/83fa38d9/attachment-0001.html>

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

Message: 2
Date: Mon, 18 Aug 2014 23:12:17 +0200
From: Frerich Raabe <[email protected]>
To: <[email protected]>
Subject: Re: [Haskell-beginners] Data.Stream interleave implementation
        question
Message-ID: <[email protected]>
Content-Type: text/plain; charset=UTF-8; format=flowed

On 2014-08-18 20:22, Curt McDowell wrote:
> Funny, I was trying the same Homework, implemented interleaveStreams using
> the same algorithm you did (taking one item from each stream per recursive
> call), and got the same result with the ruler function hanging. It was 
> also
> fixed by changing interleaveStreams to take from just one stream per call
> and switch back and forth between streams.

I hit the same problem when I did the exercise. In fact, it made me post
this question on StackOverflow, asking about how pattern matching might 
cause
the function to work differently:

http://stackoverflow.com/questions/25078598/why-would-using-head-tail-instead-of-pattern-matching-make-evaluation-terminate

I thought the answers were quite enlightening, if only to emphasize that
debugging this kind of problem is really difficult (to me). I only noticed
that not using pattern matching for the second argument of 'interleave' 
helps
by accident...

-- 
Frerich Raabe - [email protected]
www.froglogic.com - Multi-Platform GUI Testing


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

Message: 3
Date: Mon, 18 Aug 2014 17:58:44 -0600
From: Dimitri DeFigueiredo <[email protected]>
To: The Haskell-Beginners Mailing List - Discussion of primarily
        beginner-level topics related to Haskell <[email protected]>
Subject: Re: [Haskell-beginners] Disappointing thought on Haskell -- a
        simple space leak on "insert" is hard bug to catch
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed

Hi Heinrich,

Thanks so much! :-)

Wow! I was totally wrong on that one then. I got it that lazy evaluation 
is the culprit here. Now, I am still a little uneasy about insert 
producing a new version of the tree when it is not needed. Can't that 
come back to bite me later depending on how I use it?

In your explanation, you say that "the old path is usually not 
referenced anywhere, and can be garbage collected immediately."
I am a little uneasy about the "usually". Could you expand on that? What 
if it is? Could that happen? Or does that just imply a bigger constant?


Thanks again,


Dimitri


Em 16/08/14 04:13, Heinrich Apfelmus escreveu:
> Dimitri DeFigueiredo wrote:
>> Here's a problem I just found with Haskell (and maybe functional 
>> programming) that I would like to know how to avoid.
>>
>> Please don't get me wrong. I'm in *LUUV* with Haskell! :-)
>>
>>
>> Exercise 2.3 of Chris Okasaki's book "Purely Functional Data
>> Structures" shows that something as simple as an insert function in a
>> binary tree can cause a space leak in Haskell. (and other functional
>> languages as well)
>>
>> Here's a simple tree type:
>>
>> data Tree a = Empty
>>             | MkTree (Tree a) a (Tree a)
>>
>> Here's the version of insert with the space leak:
>>
>> -- ** SPACE LEAK! ** version
>> -- this version unnecessarily copies the path to the inserted element 
>> even if
>> -- the same element is already present in the tree.
>> -- a million insertions of the same element will cause a million trees
>> -- to exist whereone would suffice.
>>
>> treeInsert :: Ord a => a -> Tree a -> Tree a
>> treeInsert e Empty = MkTree Empty e Empty
>> treeInsert e t@(MkTree a x b) | e > x     = MkTree a x (treeInsert e b)
>>                               | e < x     = MkTree (treeInsert e a) x b
>>                               | otherwise = t
>>
>> Here's a version without the space leak:
>>
>> treeInsert :: Ord a => a -> Tree a -> Tree a
>> treeInsert e t = case (treeInsert' e t) of
>>                     Nothing -> t
>>                     Just x  -> x
>>     where
>>         treeInsert' :: Ord a => a -> Tree a -> Maybe (Tree a)
>>         treeInsert' e Empty = return $ MkTree Empty e Empty
>>         treeInsert' e (MkTree a x b) | e > x     = do {r <- 
>> treeInsert' e b; return $ MkTree a x r}
>>                                      | e < x     = do {r <- 
>> treeInsert' e a; return $ MkTree r x b}
>>                                      | otherwise = Nothing
>>
>>
>> This is so tricky that I think it is worth questioning whether
>> Haskell is helping here. First, just spotting that the first version
>> leads to a space leak is not trivial. Second, the fix is so much
>> uglier than the original version. It is disappointing to have to
>> write it!
>>
>> Questions:
>> 1) ** Is there a warning sign that would easily flag this space leak? **
>> 2) Is there a simpler fix?
>
> The really tricky thing here is that the space leak is not what you 
> think it is. :)
>
> When you use the tree in an ephemeral fashion, the issue is *not* that 
> the path to the element is being copied, because the old path is 
> usually not referenced anywhere, and can be garbage collected 
> immediately. Asymptotically, this has no impact on space usage.
>
> Instead, the issue is that the tree operations are not "completed". 
> Inserting the same element a thousand times without inspecting the 
> tree afterwards, you will get a tree that contains a huge unevaluated 
> subtree, like
>
>   MkTree (treeInstert 'a' (treeInsert 'a' ...)) 'f' Empty
>
> What your supposed fix actually does is that it fully evaluates the 
> subtrees as well.
>
> An easier way to achieve this to use a "strictness annotation" in the 
> data type, which is done via the `!` symbol:
>
>     data Tree a = Empty
>                 | MkTree !(Tree a) a !(Tree a)
>
> This data type may not have any unevaluated subtrees. Try it and see 
> whether it solves your problem.
>
>
> In general, lazy evaluation is a trade-off: It makes some programs 
> simpler to write, but the price is that the cost model becomes more 
> difficult, both for time and for space usage. Cost models that you may 
> know from eager languages do not apply anymore.
>
> For reasoning about time usage, Okasaki introduces the "debit 
> method",w hich you've certainly read about. Another exposition can be 
> found in [1].
>
> For reasoning about space, I recommend an approach that I like to call 
> "space invariants" [2]. The key problem with the space leak above is 
> that the semantics of a tree -- which elements it contains -- no 
> longer coincides with the size of its representation -- an expression 
> which may be only partially evaluated. For things like infinite lists, 
> e.g. [1..], this is actually great! But for other things like finite 
> maps, this may lead to unexpected space usage. The remedy is to 
> enforce a "space invariant", which is a guarantee that links the 
> semantics and the size of the representation. An example would be "A 
> tree in WHNF uses only as much space as the leaves it contains (+ 
> skeleton)". The annotion `!` is one way to enforce these invariants.
>
>
>   [1]: http://apfelmus.nfshost.com/articles/debit-method.html
>   [2]: http://apfelmus.nfshost.com/blog/2013/08/21-space-invariants.html
>
>
> Best regards,
> Heinrich Apfelmus
>
> -- 
> http://apfelmus.nfshost.com
>
>
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners



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

Message: 4
Date: Tue, 19 Aug 2014 10:37:48 +0200
From: Elise Huard <[email protected]>
To: The Haskell-Beginners Mailing List - Discussion of primarily
        beginner-level topics related to Haskell <[email protected]>
Subject: Re: [Haskell-beginners] Using Traversal as a kind of pointer
Message-ID:
        <CAHfyCq=0g0nya8tmf49nyfebcxyhsgsi5otwtjivhjg3_o0...@mail.gmail.com>
Content-Type: text/plain; charset=UTF-8

Thanks for the example! I found another example of filtered here
http://www.haskellforall.com/2013/05/program-imperatively-using-haskell.html
I'm aware that filtered traversals should only ever be used with
functions that will not change the number of elements filtered.
Thank you!

Elise

On 18 August 2014 16:03, Daniel Trstenjak <[email protected]> wrote:
>
> Hi Elise,
>
>> thanks for your answer. That looks like something that might work -
>> however,  having never worked with Optics, I'm not entirely sure
>> whether I'm doing it right, getting an error:
>
> oh sorry, there has to be a 'traversed' before the 'filtered'.
>
>> Also, may I ask what the '&' is in your proposed solution?
>
> The '&' is just applying a lens to a variable.
>
>
> So here's a working example:
>
>    {-# LANGUAGE Rank2Types #-}
>
>    import Control.Lens
>
>    type Background = Int
>    type Lifeform   = Int
>    type Player     = Int
>
>
>    data World = World Background [Lifeform] deriving (Show)
>
>
>    lifeforms :: Lens' World [Lifeform]
>    lifeforms = lens getLifeforms setLifeforms
>       where
>          getLifeforms (World _ lifeforms)    = lifeforms
>          setLifeforms (World bg _) lifeforms = World bg lifeforms
>
>
>    colliding :: Player -> Traversal' [Lifeform] Lifeform
>    colliding player = traversed . filtered (== player)
>
>
> If you load this into ghci und can write:
>
>    > World 1 [1, 2] & lifeforms . colliding 1 %~ (+ 10)
>    > World 1 [11,2]
>
>
> Greetings,
> Daniel
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners


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

Subject: Digest Footer

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


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

End of Beginners Digest, Vol 74, Issue 16
*****************************************

Reply via email to