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.  partial application (Miguel Negrao)
   2. Re:  partial application (Brent Yorgey)
   3.  fibonacci and concurrent recursion (Christoffer Buchholz)
   4. Re:  fibonacci and concurrent recursion (Brent Yorgey)
   5. Re:  partial application (Brent Yorgey)
   6. Re:  fibonacci and concurrent recursion (Dennis Felsing)
   7. Re:  fibonacci and concurrent recursion (Christoffer Buchholz)


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

Message: 1
Date: Mon, 3 Dec 2012 12:28:08 +0000
From: Miguel Negrao <[email protected]>
Subject: [Haskell-beginners] partial application
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii

Hi list,

Is there a syntax in Haskell for partial application that would be something 
like this the following ?

f a b c d  = a +b+ c+ d

g = f _ 1 2 3 

or the only way to do it is like below ?

g = (\x -> f x 1 2 3) 

Also, hlint complains about top-level functions without type even if they are 
not exported out of the corresponding module. Is is really bad style not put 
type signatures in all top-level functions ? I really like the fact that 
haskell takes care of the type signatures for me.

best,
Miguel
http://www.friendlyvirus.org/miguelnegrao/







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

Message: 2
Date: Mon, 3 Dec 2012 07:53:58 -0500
From: Brent Yorgey <[email protected]>
Subject: Re: [Haskell-beginners] partial application
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii

On Mon, Dec 03, 2012 at 12:28:08PM +0000, Miguel Negrao wrote:
> Hi list,
> 
> Is there a syntax in Haskell for partial application that would be something 
> like this the following ?
> 
> f a b c d  = a +b+ c+ d
> 
> g = f _ 1 2 3 
> 
> or the only way to do it is like below ?
> 
> g = (\x -> f x 1 2 3) 

Yes, a lambda is the only way to do it.

>  Also, hlint complains about top-level functions without type even
> if they are not exported out of the corresponding module. Is is
> really bad style not put type signatures in all top-level functions
> ? I really like the fact that haskell takes care of the type
> signatures for me.

Yes, it is bad style.  Let me give you two reasons why I always
encourage putting type signatures on all top-level functions.  Whether
they are exported or not really makes no difference.

  1. Writing the type signature for a function *first*, before
     implementing it, really helps a LOT in clarifying things in your
     own mind.  If you cannot write down the intended type of a
     function then you do not understand what it is supposed to do.
     If you do not understand what it is supposed to do then how do
     you expect to be able to implement it?

  2. Suppose you make a mistake when implementing a function.  If you
     don't give a type signature, it's possible that GHC will infer
     some type for it anyway (but not the type you intended!).  Now
     you will not get an error until further down the line when you
     use that function somewhere else.  And what's more, the error
     will not tell you anything about the real problem.  It will just
     say "X does not match Y on line 297" and you will have to do a
     lot of work to figure out that the real problem is that you
     messed up in implementing function foo on line 43.  But if you
     had put a type signature on foo in the first place, you would
     have gotten an error immediately.

-Brent



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

Message: 3
Date: Mon, 3 Dec 2012 16:05:28 +0100
From: Christoffer Buchholz <[email protected]>
Subject: [Haskell-beginners] fibonacci and concurrent recursion
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="utf-8"

Hi 

I have been looking at this fibonacci implementation:

f = 0:1:(zipWith (+) f (tail f))

and I have been trying to fit it inside my head. I am not quite there yet, 
though.

I have been tracing the steps manually like this

0:1

[0,1]
[1]

0:1:1

[0,1,1]
[1,1]

0:1:1:2

[0,1,1,2]
[1,1,2]

0:1:1:2:3

[0,1,1,2,3]
[1,1,2,3]

0:1:1:2:3:5

And it is easy to see that it works, but what I do not understand is how the 
two recursive applications progress. How do they evolve concurrently? For each 
execution of `f`, `f` will be executed twice. So how does all these results end 
up in the same list?

I guess a more general way of asking my question is how does concurrent 
recursion on the same result-set work? 

-- 
Christoffer Buchholz

-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20121203/5ce4c9ca/attachment-0001.htm>

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

Message: 4
Date: Mon, 3 Dec 2012 10:31:09 -0500
From: Brent Yorgey <[email protected]>
Subject: Re: [Haskell-beginners] fibonacci and concurrent recursion
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii

Hi Chris,

On Mon, Dec 03, 2012 at 04:05:28PM +0100, Christoffer Buchholz wrote:
> Hi 
> 
> I have been looking at this fibonacci implementation:
> 
> f = 0:1:(zipWith (+) f (tail f))
> 
> and I have been trying to fit it inside my head. I am not quite there yet, 
> though.
> 
> And it is easy to see that it works, but what I do not understand is how the 
> two recursive applications progress. How do they evolve concurrently? For 
> each execution of `f`, `f` will be executed twice. So how does all these 
> results end up in the same list?

f is not 'executed'.  And it certainly is not executed twice for each
execution, or anything like that.

f is simply a *name* for an *expression*.  All three occurrences of f
in the code above refer to the *same* expression.  They do not "evolve
concurrently", they simply *are* the same thing.  Operationally, they
are all represented by pointers to the exact same list structure in
memory.  Note also that simply referring to an expression does not
'do' anything; when I said 'Hi Chris' above, it did not cause you to
be 'executed'.  I simply referred to you, and you went on being the
same person you were all along.

The thing to think about is not execution but the *process of
evaluation*.  Unlike people, Haskell expressions can be partially
evaluated, and the process of evaluation happens on demand.
Unfortunately it is very difficult to show the process of evaluation
in an email because for this expression it really requires thinking
about the expression as a *graph*, and those are hard to draw in an
email.

At first f looks like this:

  f = 0 : 1 : zipWith (+) f (tail f)

Now, if we demand to know the next element of the list, we need to
evaluate the call to zipWith.  zipWith, in turn, demands to know the
first elements of its arguments.  Well, we can see that the first
element of f is 0, and the first element of (tail f) is 1.  So the
next element of the list is (0+1) = 1.  At this point f looks like
this:

  f = 0 : f'@(1 : f''@(1 : zipWith (+) f' f''))

Here's where a picture would be really helpful.  Instead of drawing a
graph I have given certain parts of the expression names.  You can see
that the arguments to zipWith are really just pointers back to
subexpressions of f itself.  Continuing, the next step would look like
this:

  f = 0 : 1 : f'@(1 : f''@(2 : zipWith (+) f' f''))

And so on.

I hope that was at least somewhat helpful, though I suspect you will
probably still be confused.  That's OK though; embrace the confusion
and keep asking questions. =)

-Brent



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

Message: 5
Date: Mon, 3 Dec 2012 10:41:46 -0500
From: Brent Yorgey <[email protected]>
Subject: Re: [Haskell-beginners] partial application
To: [email protected],      Miguel Negrao
        <[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain; charset=utf-8

On Mon, Dec 03, 2012 at 03:20:41PM +0000, Miguel Negrao wrote:
> 
> A 03/12/2012, ?s 12:53, Brent Yorgey escreveu:
> >> Is there a syntax in Haskell for partial application that would be 
> >> something like this the following ?
> >> 
> >> f a b c d  = a +b+ c+ d
> >> 
> >> g = f _ 1 2 3 
> > Yes, a lambda is the only way to do it.
> 
> Given how compact haskell?s syntax can be, is there a reason why implementing 
> such placeholders is not a good idea for haskell ?

Yes: it would introduce horrible ambiguity.  Consider

  (f (g _ 1 2))

Does it mean

  (f (\x -> g x 1 2))

or

  (\x -> f (g x 1 2))

?  I don't know of any good reason to prefer one over the other.  Any
rule you come up with is likely to have other weird corner cases you
hadn't considered.  As I understand it, Scala actually does have this
feature, along with lots of confusing, ugly, ad-hoc rules to
disambiguate situations like the above.

> >  2. Suppose you make a mistake when implementing a function.  If you
> >     don't give a type signature, it's possible that GHC will infer
> >     some type for it anyway (but not the type you intended!).  Now
> >     you will not get an error until further down the line when you
> >     use that function somewhere else.  And what's more, the error
> >     will not tell you anything about the real problem.  It will just
> >     say "X does not match Y on line 297" and you will have to do a
> >     lot of work to figure out that the real problem is that you
> >     messed up in implementing function foo on line 43.  But if you
> >     had put a type signature on foo in the first place, you would
> >     have gotten an error immediately.

>  Ok, I see your points. Number 2 does happen to me from time to
> time, at which point I go back to the a point where the code worked
> and introduce the type signatures with hlint, so yeah doing the
> signatures would save me from having to do that.  Sometimes I know
> how to write a function but I don?t know how to write the type
> signature because they are too complicated for my still reduced
> knowledge of haskell, for instance, I don?t know when I need to use
> the forall thing, which hlint sometimes introduces when it produces
> the type signatures. Perhaps the problem might be that I should be
> using less top-level functions and defining some of those functions
> where they are used ? A lot of my top-level functions are used only
> in one place in the code, I just code them as top-level so that I
> can test them in ghci if I need to.

No, I don't think using less top-level functions will solve anything.
In the case where you don't know how to write a type because it is too
complex, or requires features you don't understand, I think it is
reasonable to write it, ask GHCI for its type signature, make sure it
looks reasonable, and then add it to your file.  But I would hope this
situation makes up a minority of cases.  One could also question the
wisdom of writing code that requires type system features you don't
understand.

-Brent



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

Message: 6
Date: Mon, 3 Dec 2012 18:06:36 +0100
From: Dennis Felsing <[email protected]>
Subject: Re: [Haskell-beginners] fibonacci and concurrent recursion
To: Brent Yorgey <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii

On 2012-12-03T10:31-0500, Brent Yorgey wrote:
> Unfortunately it is very difficult to show the process of evaluation
> in an email because for this expression it really requires thinking
> about the expression as a *graph*, and those are hard to draw in an
> email.

I think this is a good example of using ghc-vis, so I just added it to
my examples, in case anyone wants to see the graph version:

http://felsin9.de/nnis/ghc-vis/#fibonacci

Dennis



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

Message: 7
Date: Mon, 3 Dec 2012 20:10:00 +0100
From: Christoffer Buchholz <[email protected]>
Subject: Re: [Haskell-beginners] fibonacci and concurrent recursion
To: Brent Yorgey <[email protected]>
Cc: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="utf-8"

All right, thanks for clearing up my misconceptions! 

I'm trying to understand, but I still don't think I do. Any idea how I can get 
to understand it?

When I look at your "illustration" where you named the parts, it does seem more 
clear, but I don't get how e.g. at the third number `(tail f)` equals f'' 
equals 1? f'' clearly equals 1, but `(tail f)` would equal 1:1, wouldn't it? 
Same at the fourth number, f'' clearly equals 2, but `(tail f)` would equal 
1:1:2, wouldn't it? Or am I misunderstand what `f`?

-- 
Christoffer Buchholz


On Monday den 3. December 2012 at 16.31, Brent Yorgey wrote:

> Hi Chris,
> 
> On Mon, Dec 03, 2012 at 04:05:28PM +0100, Christoffer Buchholz wrote:
> > Hi 
> > 
> > I have been looking at this fibonacci implementation:
> > 
> > f = 0:1:(zipWith (+) f (tail f))
> > 
> > and I have been trying to fit it inside my head. I am not quite there yet, 
> > though.
> > 
> > And it is easy to see that it works, but what I do not understand is how 
> > the two recursive applications progress. How do they evolve concurrently? 
> > For each execution of `f`, `f` will be executed twice. So how does all 
> > these results end up in the same list?
> 
> f is not 'executed'. And it certainly is not executed twice for each
> execution, or anything like that.
> 
> f is simply a *name* for an *expression*. All three occurrences of f
> in the code above refer to the *same* expression. They do not "evolve
> concurrently", they simply *are* the same thing. Operationally, they
> are all represented by pointers to the exact same list structure in
> memory. Note also that simply referring to an expression does not
> 'do' anything; when I said 'Hi Chris' above, it did not cause you to
> be 'executed'. I simply referred to you, and you went on being the
> same person you were all along.
> 
> The thing to think about is not execution but the *process of
> evaluation*. Unlike people, Haskell expressions can be partially
> evaluated, and the process of evaluation happens on demand.
> Unfortunately it is very difficult to show the process of evaluation
> in an email because for this expression it really requires thinking
> about the expression as a *graph*, and those are hard to draw in an
> email.
> 
> At first f looks like this:
> 
> f = 0 : 1 : zipWith (+) f (tail f)
> 
> Now, if we demand to know the next element of the list, we need to
> evaluate the call to zipWith. zipWith, in turn, demands to know the
> first elements of its arguments. Well, we can see that the first
> element of f is 0, and the first element of (tail f) is 1. So the
> next element of the list is (0+1) = 1. At this point f looks like
> this:
> 
> f = 0 : f'@(1 : f''@(1 : zipWith (+) f' f''))
> 
> Here's where a picture would be really helpful. Instead of drawing a
> graph I have given certain parts of the expression names. You can see
> that the arguments to zipWith are really just pointers back to
> subexpressions of f itself. Continuing, the next step would look like
> this:
> 
> f = 0 : 1 : f'@(1 : f''@(2 : zipWith (+) f' f''))
> 
> And so on.
> 
> I hope that was at least somewhat helpful, though I suspect you will
> probably still be confused. That's OK though; embrace the confusion
> and keep asking questions. =)
> 
> -Brent
> 
> _______________________________________________
> Beginners mailing list
> [email protected] (mailto:[email protected])
> http://www.haskell.org/mailman/listinfo/beginners
> 
> 


-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20121203/37756aac/attachment.htm>

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

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


End of Beginners Digest, Vol 54, Issue 5
****************************************

Reply via email to