I could be wrong, as I am also new to Haskell. I suppose<br>the compiler simply cannot decide which type the lists you want to compare are<br>(their constituent elements must be instances of class Eq, but more is not known).<br>
Adding type signatures will help the compiler (it should say so as well, check the<br>error messages):<br><br>testNull = ([]::[Int]) == ([]::[Int])<br><br>although I don't know why you would want to do such a thing (sorry I did not follow the<br>
whole thread).<br><br>Cheers<br>Christian<br><br><br><div class="gmail_quote">2010/10/2 <span dir="ltr"><<a href="mailto:beginners-request@haskell.org">beginners-request@haskell.org</a>></span><br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
Send Beginners mailing list submissions to<br>
<a href="mailto:beginners@haskell.org">beginners@haskell.org</a><br>
<br>
To subscribe or unsubscribe via the World Wide Web, visit<br>
<a href="http://www.haskell.org/mailman/listinfo/beginners" target="_blank">http://www.haskell.org/mailman/listinfo/beginners</a><br>
or, via email, send a message with subject or body 'help' to<br>
<a href="mailto:beginners-request@haskell.org">beginners-request@haskell.org</a><br>
<br>
You can reach the person managing the list at<br>
<a href="mailto:beginners-owner@haskell.org">beginners-owner@haskell.org</a><br>
<br>
When replying, please edit your Subject line so it is more specific<br>
than "Re: Contents of Beginners digest..."<br>
<br>
<br>
Today's Topics:<br>
<br>
1. Re: fromIntegral (Russ Abbott)<br>
<br>
<br>
----------------------------------------------------------------------<br>
<br>
Message: 1<br>
Date: Fri, 1 Oct 2010 22:52:34 -0700<br>
From: Russ Abbott <<a href="mailto:russ.abbott@gmail.com">russ.abbott@gmail.com</a>><br>
Subject: Re: [Haskell-beginners] fromIntegral<br>
To: Daniel Fischer <<a href="mailto:daniel.is.fischer@web.de">daniel.is.fischer@web.de</a>><br>
Cc: <a href="mailto:beginners@haskell.org">beginners@haskell.org</a><br>
Message-ID:<br>
<AANLkTikKF9g3MnGew5YkAK=<a href="mailto:xxszdiLHCd8a81Skqd6Kf@mail.gmail.com">xxszdiLHCd8a81Skqd6Kf@mail.gmail.com</a>><br>
Content-Type: text/plain; charset="iso-8859-1"<br>
<br>
It turns out that<br>
<br>
test1 = 1 == 1<br>
<br>
will load (and return True), but<br>
<br>
testNull = [ ] == [ ]<br>
<br>
won't load. Both 1 and [ ] seem to have similar sorts of type parameters in<br>
their types. Why are they treated differently?<br>
<br>
<br>
-- Russ<br>
<br>
<br>
<br>
On Fri, Oct 1, 2010 at 10:40 PM, Russ Abbott <<a href="mailto:russ.abbott@gmail.com">russ.abbott@gmail.com</a>> wrote:<br>
<br>
> I can even write<br>
><br>
> test =<br>
> let x = []<br>
> y = 1 : x<br>
> z = 'a' : x<br>
> in ...<br>
><br>
> But clearly I can't write tail y == tail z. Does that imply that type<br>
> inferencing prevents one from writing a True expression?<br>
><br>
><br>
> -- Russ<br>
><br>
><br>
><br>
> On Fri, Oct 1, 2010 at 10:24 PM, Russ Abbott <<a href="mailto:russ.abbott@gmail.com">russ.abbott@gmail.com</a>>wrote:<br>
><br>
>> Thanks. I'm still wondering what [ ] refers to. I can load the following<br>
>> file without error.<br>
>><br>
>> null' xs = xs == [ ]<br>
>><br>
>> test =<br>
>> let x = [ ]<br>
>> in tail [1] == x && tail ['a'] == x<br>
>><br>
>> (I know I can define null' differently. I'm defining it this way so that I<br>
>> can ask this question.)<br>
>><br>
>> When I execute test I get True.<br>
>> > test<br>
>> True<br>
>><br>
>> So my question is: what is x after compilation? Is it really a thing of<br>
>> type<br>
>> (Eq a) => [a] ?<br>
>> If so, how should I think of such a thing being stored so that it can be<br>
>> found equal to both tail [1] and tail ['a']? Furthermore, this seems to<br>
>> show that (==) is not transitive since one can't even compile<br>
>> tail [1] == tail ['a']<br>
>> much less find them to be equal. Yet they are each == to x.<br>
>><br>
>> -- Russ<br>
>><br>
>><br>
>><br>
>> On Fri, Oct 1, 2010 at 9:08 AM, Daniel Fischer <<a href="mailto:daniel.is.fischer@web.de">daniel.is.fischer@web.de</a>>wrote:<br>
>><br>
>>> On Friday 01 October 2010 17:08:08, Russ Abbott wrote:<br>
>>> > Thanks, Filipe<br>
>>> ><br>
>>> > I clearly over-stated my case. I'd like to break it into a number of<br>
>>> > different question. Please see below.<br>
>>> ><br>
>>> > On Thu, Sep 30, 2010 at 10:25 PM, Felipe Lessa<br>
>>> <<a href="mailto:felipe.lessa@gmail.com">felipe.lessa@gmail.com</a>>wrote:<br>
>>> > > I'll try to clarify some concepts. Please correct me if I am<br>
>>> > > wrong, and please forgive me if I misunderstood you.<br>
>>> > ><br>
>>> > > On Fri, Oct 1, 2010 at 12:54 AM, Russ Abbott <<a href="mailto:russ.abbott@gmail.com">russ.abbott@gmail.com</a>><br>
>>> > ><br>
>>> > > wrote:<br>
>>> > > > In explaining fromIntegral, I want to say that it is really a<br>
>>> > > > collection<br>
>>> > ><br>
>>> > > of<br>
>>> > ><br>
>>> > > > overloaded functions:<br>
>>> > > ><br>
>>> > > > Integer -> Double<br>
>>> > > > Int -> Float<br>
>>> > > > ...<br>
>>> > > ><br>
>>> > > > When GHC compiles a line of code with fromIntegral it in, it must<br>
>>> > > > decide<br>
>>> > ><br>
>>> > > at<br>
>>> > ><br>
>>> > > > compile time which of these overloaded functions to compile to.<br>
>>> > > > This is<br>
>>> > ><br>
>>> > > in<br>
>>> > ><br>
>>> > > > contrast to saying that fromIngetral is a function of the type<br>
>>> > > > (Integral<br>
>>> > ><br>
>>> > > a,<br>
>>> > ><br>
>>> > > > Num b) => a -> b. In reality there is no (single) function of the<br>
>>> > > > type (Integral a, Num b) => a -> b because (among other things)<br>
>>> > > > every function must map between actual types, but (Integral a, Num<br>
>>> > > > b) => a -> b does not say which actual types are mapped between.<br>
>>> > > ><br>
>>> > > > Is the preceding a reasonable thing to say?<br>
>>> > ><br>
>>> > > First of all, I do think that polymorphic functions are plain ol'<br>
>>> > > functions. For example<br>
>>> > ><br>
>>> > > id :: a -> a<br>
>>> > > id x = x<br>
>>> > ><br>
>>> > > is a function. Moreover, in GHC 'id' has only one<br>
>>> > > representation, taking a thunk and returning a thunk, so even at<br>
>>> > > the machine code level this is only one function.<br>
>>> ><br>
>>> > Agree. I over stated my case. The same can be said for<br>
>>> > length :: [a] -> Int<br>
>>> > It doesn't matter what the type of element in the list is. length runs<br>
>>> > the same way no matter what. So this is pure polymorphism.<br>
>>> ><br>
>>> > > Now, maybe 'fromIntegral' has something more than polymorphism?<br>
>>> > > Well, it has typeclasses. But we can represent those as<br>
>>> > > data types, so we could write<br>
>>> > ><br>
>>> > > fromIntegralD :: Integral a -> Num b -> a -> b<br>
>>> > > fromIntegralD intrDictA numDictB =<br>
>>> > > fromIntegral numDictB . toInteger intrDictA<br>
>>> ><br>
>>> > I'm afraid I don't understand this. Moreover, I couldn't get the<br>
>>> > preceding to load without error.<br>
>>> ><br>
>>><br>
>>> No wonder, Integral and Num are type classes and not datatypes (unless<br>
>>> you<br>
>>> have defined such datatypes in scope).<br>
>>><br>
>>> The point is, you can represent type classes as dictionaries, e.g.<br>
>>><br>
>>> data Num a = NumDict<br>
>>> { plus :: a -> a -> a<br>
>>> , minus :: a -> a -> a<br>
>>> , ...<br>
>>> , fromIntegerD :: Integer -> a<br>
>>> }<br>
>>><br>
>>> data Integral a = IntegralDict<br>
>>> { quotD :: a -> a -> a<br>
>>> , ...<br>
>>> , toIntegerD a<br>
>>> }<br>
>>><br>
>>> Then a type-class polymorphic function like fromIntegral becomes a<br>
>>> function<br>
>>> with some dictionaries as additional arguments.<br>
>>><br>
>>> foo :: (Class1 a, Class2 b) => a -> b<br>
>>><br>
>>> becomes<br>
>>><br>
>>> fooDict :: Class1Dict a -> Class2Dict b -> a -> b<br>
>>><br>
>>> To do that explicitly is of course somewhat cumbersome as one has to<br>
>>> always<br>
>>> carry the dictionaries around and one can have more than one dictionary<br>
>>> per<br>
>>> type (e.g.<br>
>>><br>
>>> intNum1 :: Num Int<br>
>>> intNum1 = NumDict<br>
>>> { plus = (+)<br>
>>> , ...<br>
>>> , fromIntegerD = fromInteger<br>
>>> }<br>
>>><br>
>>> intNum2 :: Num Int<br>
>>> intNum2 = NumDict<br>
>>> { plus = quot<br>
>>> , -- more nonsense<br>
>>> , fromInteger = const 1<br>
>>> }<br>
>>> ).<br>
>>><br>
>>> Internally, GHC implements type classes via dictionaries and passes them<br>
>>> as<br>
>>> extra arguments to overloaded functions, as you can see by inspecting the<br>
>>> Core output (-ddump-simpl).<br>
>>><br>
>>> > > Better yet, the compiler could write this code for us internally.<br>
>>><br>
>>> And GHC does.<br>
>>><br>
>>> > > Now, using thunks we can get a single machine code for<br>
>>> > > 'fromIntegralD' as well.<br>
>>><br>
>>> But that's not terribly efficient, so with -O, GHC tries to eliminate<br>
>>> dictionaries and use the specialised functions (like<br>
>>> plusInteger :: Integer -> Integer -> Integer).<br>
>>><br>
>>> > ><br>
>>> > > In sum, I think all functions are really just that, functions.<br>
>>> > ><br>
>>> > > --<br>
>>> > ><br>
>>> > > You may call functions that have typeclass constraints<br>
>>> > > "overloaded functions", but they still are functions.<br>
>>> > ><br>
>>> > > Functions that are polymorphic but do not have constraints are<br>
>>> > > not really overloaded because of parametricity, which means that<br>
>>> > > they can't change the way they work based on the specific choices<br>
>>> > > of types you make.<br>
>>> ><br>
>>> > I don't understand the preceding paragraph. Would you mind elaborating.<br>
>>> ><br>
>>><br>
>>> For a function like<br>
>>><br>
>>> length :: [a] -> Int<br>
>>><br>
>>> , because it doesn't know anything about the type a at which it will be<br>
>>> called, it cannot do anything with the contents of the list (well, it<br>
>>> could<br>
>>> call seq on them, but it would do that for every type), it can only<br>
>>> inspect<br>
>>> the spine of the list.<br>
>>><br>
>>> The code is completely independent of what type of data the pointers to<br>
>>> the<br>
>>> contents point to, so `length [True,False]' and `length [()]' can and do<br>
>>> call the exact same machine code.<br>
>>><br>
>>> > > > If so, can I say the same sort of thing about constants like 1 and<br>
>>> > > > []? In particular there is no single value []. Instead [] is a<br>
>>> > > > symbol which at compile time must be compiled to the empty list of<br>
>>> > > > some particular type, e.g., [Int]. There is no such Haskell value<br>
>>> > > > as [] :: [a] since [a] (as type) is not an actual type. I want to<br>
>>> > > > say the same thing about 1, i.e., that there is no such Haskell<br>
>>> > > > value as 1 :: (Num t) => t. When the symbol<br>
>>> > ><br>
>>> > > 1<br>
>>> > ><br>
>>> > > > appears in a program, the compiler must decide during compilation<br>
>>> > > > whether<br>
>>> > ><br>
>>> > > it<br>
>>> > ><br>
>>> > > > is intended to be 1::Int or 1::Integer or 1::Double, etc.<br>
>>> > ><br>
>>> > > Well, [a] *is* an actual type, a polymorphic one.<br>
>>> ><br>
>>> > Here is the example that raised that issue for me. Let's say I define<br>
>>> > null' as follows.<br>
>>> ><br>
>>> > null' xs = xs == [ ]<br>
>>> ><br>
>>> > If I don't include a declaration in the file, Haskell (reasonably)<br>
>>> > concludes the following.<br>
>>> ><br>
>>> > > :t null'<br>
>>> ><br>
>>> > null' :: (Eq a) => [a] -> Bool<br>
>>> ><br>
>>> > If I write the following at the top level,<br>
>>><br>
>>> You seem to mean the ghci prompt here, not the top level of a module.<br>
>>><br>
>>> > everything is fine.<br>
>>> ><br>
>>> > > null' [ ]<br>
>>> ><br>
>>> > True<br>
>>> ><br>
>>> > But if I include the following in the file that defines null', I get an<br>
>>> > error message.<br>
>>> ><br>
>>> > test = null' [ ]<br>
>>> ><br>
>>> > Ambiguous type variable `a' in the constraint:<br>
>>> > `Eq a' arising from a use of `null'' at null.hs:6:17-24<br>
>>> > Probable fix: add a type signature that fixes these type<br>
>>> > variable(s)<br>
>>> ><br>
>>> > Why is that?<br>
>>><br>
>>> null' has an Eq constraint, so to evaluate test, an Eq dictionary is<br>
>>> needed, but there's no way to determine which one should be used.<br>
>>><br>
>>> At a lower level, the type of null' is<br>
>>><br>
>>> null' :: EqDict a -> [a] -> Bool<br>
>>><br>
>>> The (hidden) first argument is missing and GHC doesn't know which one to<br>
>>> pass.<br>
>>><br>
>>> At the ghci-prompt, ghci's extended default rules let it selet the Eq<br>
>>> dictionary of () and all's fine.<br>
>>><br>
>>> In a source file, GHC restricts itself to the default rules specified in<br>
>>> the language report, which state that for defaulting to take place, at<br>
>>> least one of the constraints must be a numeric class. There's none here,<br>
>>> so<br>
>>> no defaulting and the type variable of the constraint remains ambiguous.<br>
>>><br>
>>> > And how can it be fixed? I know I can fix it as follows.<br>
>>> ><br>
>>> > test = null' ([ ] :: [Integer])<br>
>>> ><br>
>>> > > :reload<br>
>>> > ><br>
>>> > > test<br>
>>> ><br>
>>> > True<br>
>>><br>
>>> In that situation, I think giving a type signature is the only way¹.<br>
>>><br>
>>> test = null' ([] :: Num a => [a])<br>
>>><br>
>>> also works.<br>
>>><br>
>>> ¹ -XExtendedDefaultRules might work too.<br>
>>> ><br>
>>> > That's what suggested to me that [ ] had to be compiled into a concrete<br>
>>> > value.<br>
>>><br>
>>> Try<br>
>>><br>
>>> null'' [] = True<br>
>>> null'' _ = False<br>
>>><br>
>>> test'' = null'' []<br>
>>><br>
>>> No type class constraints, no problems.<br>
>>><br>
>>> ><br>
>>> ><br>
>>> > It seemed to me that similar reasoning applied to things like 1. How<br>
>>> is<br>
>>> > the following explained?<br>
>>> ><br>
>>> > Prelude> 111111111111111111111111111111111111111111<br>
>>> > 111111111111111111111111111111111111111111<br>
>>> > it :: (Num t) => t<br>
>>> > Prelude> maxBound :: Int<br>
>>> > 2147483647<br>
>>> > it :: Int<br>
>>> > Prelude> 111111111111111111111111111111111111111111 - (1::Int)<br>
>>> > -954437178<br>
>>> > it :: Int<br>
>>> ><br>
>>> > Does it make sense to say that the long string of 1's is really of type<br>
>>> > (Num t) => t?<br>
>>><br>
>>> Integer literals stand for (fromInteger Integer-value-of-literal), so the<br>
>>> literal itself can have any type belonging to Num. If you force it to<br>
>>> have<br>
>>> a particular type, the corresponding fromInteger function is determined<br>
>>> and<br>
>>> can be applied if the value is needed.<br>
>>><br>
>>> ><br>
>>> > If so, what does the compiler think it's doing when it processes(?) it<br>
>>> > as an Int so that it can subtract 1 :: Int from it? It didn't treat it<br>
>>> > as maxBound :: Int. And yet it didn't generate an error message.<br>
>>><br>
>>> For efficiency, fromInteger wraps, for a b-bit Integral type, the result<br>
>>> of<br>
>>> fromInteger n is n `mod` 2^b.<br>
>>><br>
>>> ><br>
>>> > Thanks<br>
>>> ><br>
>>> > -- Russ<br>
>>><br>
>>><br>
>><br>
><br>
-------------- next part --------------<br>
An HTML attachment was scrubbed...<br>
URL: <a href="http://www.haskell.org/pipermail/beginners/attachments/20101002/23bab169/attachment.html" target="_blank">http://www.haskell.org/pipermail/beginners/attachments/20101002/23bab169/attachment.html</a><br>
<br>
------------------------------<br>
<br>
_______________________________________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org">Beginners@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/beginners" target="_blank">http://www.haskell.org/mailman/listinfo/beginners</a><br>
<br>
<br>
End of Beginners Digest, Vol 28, Issue 5<br>
****************************************<br>
</blockquote></div><br>