
Dear All I have just started learning Haskell, using the O'Reilly book Real World Haskell [1]. I'm finding it a very exciting language, and I'm working my way painstakingly through the book (I'm up to the exercises at the end of Chapter 3). I have a query based on some code from the book. This question has been asked on the book web site [2], but no answer. I have also Googled about and scanned the documentation. So, here is some code (quoted from [3]): two implementations of a function to return the second element of a list. I have commented out the type signatures. -- file: rwh_examples2/ch03/MySecond.hs -- safeSecond :: [a] -> Maybe a safeSecond [] = Nothing safeSecond xs = if null (tail xs) then Nothing else Just (head (tail xs)) -- tidySecond :: [a] -> Maybe a tidySecond (_:x:_) = Just x tidySecond _ = Nothing My query concerns the inferred types of these functions --- the types inferred when the type signatures are commented out. Here's a ghci session: Prelude> :load seconds.hs [1 of 1] Compiling Main ( seconds.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> :type safeSecond safeSecond :: [a] -> Maybe a *Main> *Main> :type tidySecond tidySecond :: [t] -> Maybe t *Main> Why is safeSecond type [a] -> Maybe a, and tidySecond type [t] -> Maybe t? I mean why does one use "a" and the other "t"? What does it mean? If I change the order of the two functions in the source file, safeSecond still uses "a" and tidySecond still uses "t". Can anyone help, or point me to the right place in the documentation? In the meantime, if I find out from elsewhere I'll report back here. Thanks and best wishes Ivan [1] http://book.realworldhaskell.org/ [2] http://book.realworldhaskell.org/read/defining-types-streamlining-functions.... [3] http://book.realworldhaskell.org/read/defining-types-streamlining-functions.... -- ============================================================ Ivan A. Uemlianin Speech Technology Research and Development ivan@llaisdy.com www.llaisdy.com llaisdy.wordpress.com www.linkedin.com/in/ivanuemlianin "Froh, froh! Wie seine Sonnen, seine Sonnen fliegen" (Schiller, Beethoven) ============================================================

Good question, but I'm afraid the answer will be a bit disappointing. The
real answer is, it doesn't matter - the following types are all the same:
a -> a
b -> b
t -> t
supercalifragilisticexpialodocious -> supercalifragilisticexpialodocious
As for why it actually happens in this case, it's no doubt related to the
particular algorithm ghci uses to do the type inference.
On Sat, May 30, 2009 at 4:37 PM, Ivan Uemlianin
Dear All
I have just started learning Haskell, using the O'Reilly book Real World Haskell [1]. I'm finding it a very exciting language, and I'm working my way painstakingly through the book (I'm up to the exercises at the end of Chapter 3).
I have a query based on some code from the book. This question has been asked on the book web site [2], but no answer. I have also Googled about and scanned the documentation.
So, here is some code (quoted from [3]): two implementations of a function to return the second element of a list. I have commented out the type signatures.
-- file: rwh_examples2/ch03/MySecond.hs
-- safeSecond :: [a] -> Maybe a
safeSecond [] = Nothing safeSecond xs = if null (tail xs) then Nothing else Just (head (tail xs))
-- tidySecond :: [a] -> Maybe a
tidySecond (_:x:_) = Just x tidySecond _ = Nothing
My query concerns the inferred types of these functions --- the types inferred when the type signatures are commented out. Here's a ghci session:
Prelude> :load seconds.hs [1 of 1] Compiling Main ( seconds.hs, interpreted ) Ok, modules loaded: Main. *Main> *Main> :type safeSecond safeSecond :: [a] -> Maybe a *Main> *Main> :type tidySecond tidySecond :: [t] -> Maybe t *Main>
Why is safeSecond type [a] -> Maybe a, and tidySecond type [t] -> Maybe t? I mean why does one use "a" and the other "t"? What does it mean? If I change the order of the two functions in the source file, safeSecond still uses "a" and tidySecond still uses "t".
Can anyone help, or point me to the right place in the documentation? In the meantime, if I find out from elsewhere I'll report back here.
Thanks and best wishes
Ivan
[1] http://book.realworldhaskell.org/ [2] http://book.realworldhaskell.org/read/defining-types-streamlining-functions.... [3] http://book.realworldhaskell.org/read/defining-types-streamlining-functions....
-- ============================================================ Ivan A. Uemlianin Speech Technology Research and Development
ivan@llaisdy.com www.llaisdy.com llaisdy.wordpress.com www.linkedin.com/in/ivanuemlianin
"Froh, froh! Wie seine Sonnen, seine Sonnen fliegen" (Schiller, Beethoven) ============================================================
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On Sun, May 31, 2009 at 4:50 AM, Andrew Wagner
Good question, but I'm afraid the answer will be a bit disappointing. The real answer is, it doesn't matter - the following types are all the same: a -> a b -> b t -> t supercalifragilisticexpialodocious -> supercalifragilisticexpialodocious
And by the way, they are called 'type variables', as other kind of variables, when without name conflict, their names don't matter. lee

Dear Andrew and Lee Thanks for your comments. Andrew Wagner wrote:
As for why it actually happens in this case, it's no doubt related to the particular algorithm ghci uses to do the type inference. Interesting. I tried it in hugs and it doesn't happen:
Main> :type safeSecond safeSecond :: [a] -> Maybe a Main> :type tidySecond tidySecond :: [a] -> Maybe a Main> So, it's a property of the ghci interpreter rather than of the language itself. Just out of curiousity, I'd be interested to know what's going on in ghci to produce this effect. Are there different types of type variable? Learning Haskell is reminding me of things I studied when I was an undergrad (linguistics)--- pattern matching in Prolog; the type system reminds me of categorial grammar; we looked at lamda calculus as part of formal semantics. So I'd like to look into this more deeply, if anyone can give me a pointer into the ghci docs. Thanks again Ivan -- ============================================================ Ivan A. Uemlianin Speech Technology Research and Development ivan@llaisdy.com www.llaisdy.com llaisdy.wordpress.com www.linkedin.com/in/ivanuemlianin "Froh, froh! Wie seine Sonnen, seine Sonnen fliegen" (Schiller, Beethoven) ============================================================

Am Sonntag 31 Mai 2009 15:37:27 schrieb Ivan Uemlianin:
Dear Andrew and Lee
Thanks for your comments.
Andrew Wagner wrote:
As for why it actually happens in this case, it's no doubt related to the particular algorithm ghci uses to do the type inference.
In particular the part where GHC assigns names to type variables.
Interesting. I tried it in hugs and it doesn't happen:
Main> :type safeSecond safeSecond :: [a] -> Maybe a Main> :type tidySecond tidySecond :: [a] -> Maybe a Main>
So, it's a property of the ghci interpreter rather than of the language itself.
Yes.
Just out of curiousity, I'd be interested to know what's going on in ghci to produce this effect. Are there different types of type variable?
There are type variables of different *kind*, e.g. in class Functor f where fmap :: (a -> b) -> f a -> f b a and b are type variables of kind * (the kind of ordinary types) and f is a type variable of kind (* -> *) (the kind of type constructors which take an ordinary type and produce another ordinary type, examples are [] and Maybe). But that has nothing to do with the phenomenon, in the inferred type signatures of safeSecond and tidySecond, the 'a' resp. 't' are both type variables of kind *. The only difference is that in one case the name supply delivered 'a' and in the other it delivered 't'.

On Sun, May 31, 2009 at 05:42:44PM +0200, Daniel Fischer wrote:
But that has nothing to do with the phenomenon, in the inferred type signatures of safeSecond and tidySecond, the 'a' resp. 't' are both type variables of kind *. The only difference is that in one case the name supply delivered 'a' and in the other it delivered 't'.
I think one source of difference is that ghci tries to maintain type variable names from declared type signatures. So perhaps one of the library functions used to define 'safeSecond' has an explicitly declared type signature that mentions 'a', and a library function used to defined 'tidySecond' has one that mentions 't'. -Brent

Brent Yorgey wrote:
On Sun, May 31, 2009 at 05:42:44PM +0200, Daniel Fischer wrote:
But that has nothing to do with the phenomenon, in the inferred type signatures of safeSecond and tidySecond, the 'a' resp. 't' are both type variables of kind *. The only difference is that in one case the name supply delivered 'a' and in the other it delivered 't'.
I think one source of difference is that ghci tries to maintain type variable names from declared type signatures. So perhaps one of the library functions used to define 'safeSecond' has an explicitly declared type signature that mentions 'a', and a library function used to defined 'tidySecond' has one that mentions 't'.
This sounds like a good answer. Thanks! I tried this: safe xs = head xs has inferred type safe :: [a] -> a tidy (x:_) = x has inferred type tidy :: [t] -> t I can rest easy now, and get on to the next exercise. Best Ivan -- ============================================================ Ivan A. Uemlianin Speech Technology Research and Development ivan@llaisdy.com www.llaisdy.com llaisdy.wordpress.com www.linkedin.com/in/ivanuemlianin "Froh, froh! Wie seine Sonnen, seine Sonnen fliegen" (Schiller, Beethoven) ============================================================
participants (5)
-
Andrew Wagner
-
Brent Yorgey
-
Daniel Fischer
-
Ivan Uemlianin
-
Lee Duhem