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. types, parentheses, application, composition (Christopher Howard)
2. Re: types, parentheses, application, composition (Daniel Fischer)
3. Re: types, parentheses, application, composition
(Brandon Allbery)
4. Re: type signature error in a where clause (Mark Wallace)
5. Re: types, parentheses, application, composition
(Christopher Howard)
6. Re: types, parentheses, application, composition (Kim-Ee Yeoh)
----------------------------------------------------------------------
Message: 1
Date: Sun, 25 Nov 2012 02:27:31 -0900
From: Christopher Howard <[email protected]>
Subject: [Haskell-beginners] types, parentheses, application,
composition
To: Haskell Beginners <[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain; charset="iso-8859-1"
Could someone explain more precisely to me what is the significance of
parentheses in the type of an expression? Are they just some kind of
syntactic sugar, that simplifies into a type without them, or are they
more like parentheses in algebra, or...?
In particular, I'm having difficulty understanding the results of
composition or application that involves parentheses... I think I've got
it figured out and then I find another strange expression that doesn't
have the type I expect. Here is an example using the (self-made)
function "sqr":
code:
--------
> :t sqr
sqr :: Double -> Double
> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
> :t (. sqr)
(. sqr) :: (Double -> c) -> Double -> c
> :t ((. sqr) .)
((. sqr) .) :: (a -> Double -> c) -> a -> Double -> c
--------
Everything makes sense up until the last expression, "((. sqr) .)".
Where did the "(a -> Double -> c)" come from? What's going on here?
--
frigidcode.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 551 bytes
Desc: OpenPGP digital signature
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20121125/7e9b4250/attachment-0001.pgp>
------------------------------
Message: 2
Date: Sun, 25 Nov 2012 14:43:47 +0100
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] types, parentheses, application,
composition
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset="us-ascii"
On Sonntag, 25. November 2012, 02:27:31, Christopher Howard wrote:
> Could someone explain more precisely to me what is the significance of
> parentheses in the type of an expression? Are they just some kind of
> syntactic sugar, that simplifies into a type without them, or are they
> more like parentheses in algebra, or...?
More like parentheses in algebra, they serve to group together parts of a
(type) expression that would be grouped differently by the precedence and/or
associativity of operators, e.g. in
foo :: (Int -> a) -> a
foo f = f 42
The function arrow associates to the right, so without them, the signature
would become Int -> (a -> a) which is an entirely different type.
Or
bar :: Either a (b -> a) -> b -> a
where it's precedence. Prefix type application binds strongest (like function
application at the value level), so we can't omit the parentheses, otherwise
we'd get
(Either a b) -> a -> b -> a
>
> In particular, I'm having difficulty understanding the results of
> composition or application that involves parentheses... I think I've got
> it figured out and then I find another strange expression that doesn't
> have the type I expect. Here is an example using the (self-made)
> function "sqr":
>
> code:
> --------
>
> > :t sqr
>
> sqr :: Double -> Double
>
> > :t (.)
>
> (.) :: (b -> c) -> (a -> b) -> a -> c
Let's be more verbose and call it
(.) :: (intermediate -> final) -> (original -> intermediate)
-> original -> final
>
> > :t (. sqr)
The section (. sqr) is equivalent to \f -> f . sqr, so sqr is the second
argument of (.) and we must unify its type with the type of the second
argument of (.), which is (original -> intermediate).
So original = Double, intermediate = Double, and here (.) is used at the more
restricted type
(.) :: (Double -> final) -> (Double -> Double) -> Double -> final
the second argument is supplied, hence its type is removed, leaving
(. sqr) :: (Double -> final) -> Double -> final
>
> (. sqr) :: (Double -> c) -> Double -> c
Yup, modulo renaming, we have exactly that.
>
> > :t ((. sqr) .)
Now, (. sqr) is used as the first argument of (.). So we must unify its type
with (intermediate -> final), the type of (.)'s first argument.
Now, the function arrow is right-associative, so we can also write
(. sqr) :: (Double -> c) -> (Double -> c)
and that makes it clear that
intermediate = (Double -> c)
final = (Double -> c)
So the outer (.) is used at type
(.) :: ((Double -> c) -> (Double -> c)) -> (original -> (Double -> c)) ->
original -> (Double -> c)
The first argument is supplied, so
((. sqr) .) :: (original -> (Double -> c)) -> original -> (Double -> c)
>
> ((. sqr) .) :: (a -> Double -> c) -> a -> Double -> c
Yup, modulo renaming and parentheses that can be omitted because -> is right-
associative, that is exactly the same.
It's just easier to see what corresponds to what with the parentheses.
> --------
>
> Everything makes sense up until the last expression, "((. sqr) .)".
> Where did the "(a -> Double -> c)" come from? What's going on here?
The pretty-printer of type signatures in ghci omits unnecessary parentheses.
Read it (a -> (Double -> c)).
While for small types like here, unnecessary parentheses can increase the
readability, for larger types, they usually decrease readability much more
(ever looked at Lisp code?), because all is drowned in parentheses.
------------------------------
Message: 3
Date: Sun, 25 Nov 2012 09:43:00 -0500
From: Brandon Allbery <[email protected]>
Subject: Re: [Haskell-beginners] types, parentheses, application,
composition
To: Christopher Howard <[email protected]>
Cc: Haskell Beginners <[email protected]>
Message-ID:
<CAKFCL4WUKytVO2dmbKxtQbPKqj+gyC3K4AZ6h2=eih4t+q-...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"
On Sun, Nov 25, 2012 at 6:27 AM, Christopher Howard <
[email protected]> wrote:
> Could someone explain more precisely to me what is the significance of
> parentheses in the type of an expression? Are they just some kind of
>
One thing you're missing is that parentheses often have multiple meanings.
Specifically, the thing that's tripping you up is a section: a partially
applied operator.
(+) is an operator, with parentheses around it to turn it into a function.
You can sometimes see this passed to e.g. fmap.
By extension, (5 +) is a section: the operator (+) with its left parameter
applied already, equivalent to \x -> 5 + x. (+ 5) has applied the right
parameter instead of the left.
If you have a parenthesized thing that starts or ends with an operator,
it's a section. Your example "> :t ((. sqr) .)" has two of them, both
partially applying (.).
--
brandon s allbery kf8nh sine nomine associates
[email protected] [email protected]
unix/linux, openafs, kerberos, infrastructure http://sinenomine.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20121125/5e739c8d/attachment-0001.htm>
------------------------------
Message: 4
Date: Sun, 25 Nov 2012 23:31:13 +0800
From: Mark Wallace <[email protected]>
Subject: Re: [Haskell-beginners] type signature error in a where
clause
To: Kim-Ee Yeoh <[email protected]>
Cc: [email protected], Daniel Fischer
<[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
> The unspoken wisdom goes something like this: the classic top-down FP way
> of coding has you sketch out most if not all of your function signatures.
> So when you hit the keyboard, a very natural thing to do is to key in all
> those signatures stubbing out definitions using "undefined". You proceed
> from there.
>
> Sometimes people just use haskell as a calculator on steroids, especially
> when solving project-euler-type problems. In which case, anything goes.
> Needless to say, if all the practice a beginner gets is project euler,
> they're missing out a lot.
Thanks very much for the tips and thought.
Nowadays I'm working with the Haskell 99 Questions, and my next target
would be Project Euler. Someone have suggested to implement Prelude by
myself. But still can't find the 'right' thing to do.
Would you mind sharing with us your experience of learning haskell? What
would you recommend or what have you done in order to improve?
On 11/25/2012 05:34 PM, Kim-Ee Yeoh wrote:
> On Sat, Nov 24, 2012 at 10:32 PM, Mark Wallace <[email protected]> wrote:
>
>>> Somehow it might seem a bit easier to me to grasp the function of a
> function with the help of type signature. I'll try just omitting the
> signatures, it's easier and more handy isn't it?
>
> The unspoken wisdom goes something like this: the classic top-down FP way
> of coding has you sketch out most if not all of your function signatures.
> So when you hit the keyboard, a very natural thing to do is to key in all
> those signatures stubbing out definitions using "undefined". You proceed
> from there.
>
> Sometimes people just use haskell as a calculator on steroids, especially
> when solving project-euler-type problems. In which case, anything goes.
> Needless to say, if all the practice a beginner gets is project euler,
> they're missing out a lot.
>
>
> -- Kim-Ee
>
>
> On Sat, Nov 24, 2012 at 10:32 PM, Mark Wallace <[email protected]> wrote:
>
>> On 11/24/2012 11:07 PM, Daniel Fischer wrote:
>>
>>> On Samstag, 24. November 2012, 22:04:15, Mark Wallace wrote:
>>>
>>>> I'm writing a merge sort function, but I get type error under such
>>>> implementation:
>>>>
>>>> mergesort :: (a -> a -> Ordering) -> [a] -> [a]
>>>> mergesort cmp xs = mergeAll (map (\x -> [x]) xs)
>>>> where
>>>> mergeAll :: [[a]] -> [a]
>>>> mergeAll [x] = x
>>>> mergeAll xs = mergeAll (mergePairs xs)
>>>>
>>>> mergePairs :: [[a]] -> [[a]]
>>>> mergePairs (a:b:xs) = merge a b : mergePairs xs
>>>> mergePairs xs = xs
>>>>
>>>> merge :: [a] -> [a] -> [a]
>>>> merge as@(a:as') bs@(b:bs')
>>>>
>>>> | cmp a b == GT = b : merge as bs'
>>>> | otherwise = a : merge as' bs
>>>>
>>>> merge [] bs = bs
>>>> merge as [] = as
>>>>
>>>> And ghc says:
>>>>
>>>> Couldn't match type `a1' with `a'
>>>> `a1' is a rigid type variable bound by
>>>> the type signature for merge :: [a1] -> [a1] -> [a1]
>>>> at
>>>> /home/ice/Study/Haskell/**tutorials/99Questions/21to30.**hs:135:7
>>>> `a' is a rigid type variable bound by
>>>> the type signature for
>>>> mergesort :: (a -> a -> Ordering) -> [a] -> [a]
>>>> at
>>>> /home/ice/Study/Haskell/**tutorials/99Questions/21to30.**hs:124:1
>>>> In the first argument of `cmp', namely `a'
>>>> In the first argument of `(==)', namely `cmp a b'
>>>> In the expression: cmp a b == GT
>>>>
>>>> But if I comment all type signatures, ghc works fine on it.
>>>> I would really appreciate it if you can point out what causes this
>>>> question?
>>>>
>>> Type variables are implicitly for all-quantified. Thus the type variable
>>> a in
>>> the signatures of the local functions is a fresh type variable and has
>>> nothing
>>> to do with the a from the top-level signature.
>>>
>>> It is equivalent to you writing
>>>
>>> merge :: [b] -> [b] -> [b]
>>>
>>> except there it is obvious that the type signature is wrong.
>>>
>>> And how to fix it without changing the structure of the program (i.e. not
>>> adding function `cmp' as a parameter of `merge' etc.).
>>>
>>> 1. Just omit the type signatures, they can be inferred.
>>>
>>> That's the portable way.
>>>
>>> 2. Bring the type variable a into scope
>>>
>>> {-# LANGUAGE ScopedTypeVariables #-}
>>>
>>> mergesort :: forall a. (a-> a-> Ordering) -> [a] -> [a]
>>>
>>> then an (unquantified) a in a local type signature refers to the type
>>> from the
>>> top-level signature.
>>>
>>> That's a GHC-only (as far as I know) way.
>>>
>> Thanks for answering so fast. And all of your answers are very helpful.
>> I've tested these two solutions, all works fine.
>> Now I understand how type signature works in such condition.
>>
>> Somehow it might seem a bit easier to me to grasp the function of a
>> function with the help of type signature.
>> I'll try just omitting the signatures, it's easier and more handy isn't it?
>>
>>
>> ______________________________**_________________
>> Beginners mailing list
>> [email protected]
>> http://www.haskell.org/**mailman/listinfo/beginners<http://www.haskell.org/mailman/listinfo/beginners>
>>
------------------------------
Message: 5
Date: Sun, 25 Nov 2012 23:17:35 -0900
From: Christopher Howard <[email protected]>
Subject: Re: [Haskell-beginners] types, parentheses, application,
composition
To: Haskell Beginners <[email protected]>
Message-ID: <[email protected]>
Content-Type: text/plain; charset="iso-8859-1"
On 11/25/2012 04:43 AM, Daniel Fischer wrote:
> On Sonntag, 25. November 2012, 02:27:31, Christopher Howard wrote:
>
> More like parentheses in algebra, they serve to group together parts of a
> (type) expression that would be grouped differently by the precedence and/or
> associativity of operators, e.g. in
>
> foo :: (Int -> a) -> a
> foo f = f 42
>
> The function arrow associates to the right, so without them, the signature
> would become Int -> (a -> a) which is an entirely different type.
>
> Or
>
> bar :: Either a (b -> a) -> b -> a
>
> where it's precedence. Prefix type application binds strongest (like function
> application at the value level), so we can't omit the parentheses, otherwise
> we'd get
>
> (Either a b) -> a -> b -> a
>
>
> Let's be more verbose and call it
>
> (.) :: (intermediate -> final) -> (original -> intermediate)
> -> original -> final
>
>
> The section (. sqr) is equivalent to \f -> f . sqr, so sqr is the second
> argument of (.) and we must unify its type with the type of the second
> argument of (.), which is (original -> intermediate).
>
> So original = Double, intermediate = Double, and here (.) is used at the more
> restricted type
>
> (.) :: (Double -> final) -> (Double -> Double) -> Double -> final
>
> the second argument is supplied, hence its type is removed, leaving
>
> (. sqr) :: (Double -> final) -> Double -> final
>
>
> Yup, modulo renaming, we have exactly that.
>
>
> Now, (. sqr) is used as the first argument of (.). So we must unify its type
> with (intermediate -> final), the type of (.)'s first argument.
>
> Now, the function arrow is right-associative, so we can also write
>
> (. sqr) :: (Double -> c) -> (Double -> c)
>
> and that makes it clear that
>
> intermediate = (Double -> c)
> final = (Double -> c)
>
> So the outer (.) is used at type
>
> (.) :: ((Double -> c) -> (Double -> c)) -> (original -> (Double -> c)) ->
> original -> (Double -> c)
>
> The first argument is supplied, so
>
> ((. sqr) .) :: (original -> (Double -> c)) -> original -> (Double -> c)
>
>
> Yup, modulo renaming and parentheses that can be omitted because -> is right-
> associative, that is exactly the same.
>
> It's just easier to see what corresponds to what with the parentheses.
>
>
> The pretty-printer of type signatures in ghci omits unnecessary parentheses.
> Read it (a -> (Double -> c)).
>
> While for small types like here, unnecessary parentheses can increase the
> readability, for larger types, they usually decrease readability much more
> (ever looked at Lisp code?), because all is drowned in parentheses.
>
Beautiful explanation. The clouds are starting to clear. In particular,
previously I did not understand that 1) parentheses are in all types but
are omitted for readability when possible, and 2) when an argument is
supplied to a function it unifies the supplied parameter type with the
argument type. Knowing this makes a huge difference in looking at these
transformations.
--
frigidcode.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 551 bytes
Desc: OpenPGP digital signature
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20121125/60532d02/attachment-0001.pgp>
------------------------------
Message: 6
Date: Mon, 26 Nov 2012 15:33:08 +0700
From: Kim-Ee Yeoh <[email protected]>
Subject: Re: [Haskell-beginners] types, parentheses, application,
composition
To: Christopher Howard <[email protected]>
Cc: Haskell Beginners <[email protected]>
Message-ID:
<CAPY+ZdR-+XvPTZGFE=+zotyhpojrnpnhd1foxem0gcmzmr7...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"
On Mon, Nov 26, 2012 at 3:17 PM, Christopher Howard <
[email protected]> wrote:
> Beautiful explanation. The clouds are starting to clear. In particular,
> previously I did not understand that 1) parentheses are in all types but
> are omitted for readability when possible, and 2) when an argument is
> supplied to a function it unifies the supplied parameter type with the
> argument type. Knowing this makes a huge difference in looking at these
> transformations.
>
(1) parens are everywhere, some of them you don't see because of default
associativity
(2) type-inferencing unification is utterly opaque and mysterious
-- Kim-Ee
> --
> frigidcode.com
>
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://www.haskell.org/pipermail/beginners/attachments/20121126/dd82c25d/attachment.htm>
------------------------------
_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners
End of Beginners Digest, Vol 53, Issue 33
*****************************************