[Haskell-beginners] fromIntegral

Russ Abbott russ.abbott at gmail.com
Fri Oct 1 11:08:08 EDT 2010


Thanks, Filipe

I clearly over-stated my case.  I'd like to break it into a number of
different question.  Please see below.


On Thu, Sep 30, 2010 at 10:25 PM, Felipe Lessa <felipe.lessa at gmail.com>wrote:

> I'll try to clarify some concepts.  Please correct me if I am
> wrong, and please forgive me if I misunderstood you.
>
> On Fri, Oct 1, 2010 at 12:54 AM, Russ Abbott <russ.abbott at gmail.com>
> wrote:
> > In explaining fromIntegral, I want to say that it is really a collection
> of
> > overloaded functions:
> >
> > Integer -> Double
> > Int -> Float
> > ...
> >
> > When GHC compiles a line of code with fromIntegral it in, it must decide
> at
> > compile time which of these overloaded functions to compile to.  This is
> in
> > contrast to saying that fromIngetral is a function of the type (Integral
> a,
> > Num b) => a -> b.  In reality there is no (single) function of the type
> > (Integral a, Num b) => a -> b because (among other things) every function
> > must map between actual types, but (Integral a, Num b) => a -> b does not
> > say which actual types are mapped between.
> >
> > Is the preceding a reasonable thing to say?
>
> First of all, I do think that polymorphic functions are plain ol'
> functions.  For example
>
>  id :: a -> a
>  id x = x
>
> is a function.  Moreover, in GHC 'id' has only one
> representation, taking a thunk and returning a thunk, so even at
> the machine code level this is only one function.
>

Agree.  I over stated my case.  The same can be said for
  length  :: [a] -> Int
It doesn't matter what the type of element in the list is. length runs the
same way no matter what. So this is pure polymorphism.


>
> Now, maybe 'fromIntegral' has something more than polymorphism?
> Well, it has typeclasses.  But we can represent those as
> data types, so we could write
>
>  fromIntegralD :: Integral a -> Num b -> a -> b
>  fromIntegralD intrDictA numDictB =
>    fromIntegral numDictB . toInteger intrDictA
>

I'm afraid I don't understand this. Moreover, I couldn't get the preceding
to load without error.

>
> Better yet, the compiler could write this code for us internally.
> Now, using thunks we can get a single machine code for
> 'fromIntegralD' as well.
>
> In sum, I think all functions are really just that, functions.
>
> --
>
> You may call functions that have typeclass constraints
> "overloaded functions", but they still are functions.
>
> Functions that are polymorphic but do not have constraints are
> not really overloaded because of parametricity, which means that
> they can't change the way they work based on the specific choices
> of types you make.
>

I don't understand the preceding paragraph. Would you mind elaborating.

>
> > If so, can I say the same sort of thing about constants like 1 and []? In
> > particular there is no single value []. Instead [] is a symbol which at
> > compile time must be compiled to the empty list of some particular type,
> > e.g., [Int].  There is no such Haskell value as [] :: [a] since [a] (as
> > type) is not an actual type. I want to say the same thing about 1, i.e.,
> > that there is no such Haskell value as 1 :: (Num t) => t. When the symbol
> 1
> > appears in a program, the compiler must decide during compilation whether
> it
> > is intended to be 1::Int or 1::Integer or 1::Double, etc.
>
> Well, [a] *is* an actual type, a polymorphic one.
>

Here is the example that raised that issue for me. Let's say I define null'
as follows.

   null' xs = xs == [ ]

If I don't include a declaration in the file, Haskell (reasonably) concludes
the following.

  > :t null'
  null' :: (Eq a) => [a] -> Bool

If I write the following at the top level, everything is fine.
  > null' [ ]
  True

But if I include the following in the file that defines null', I get an
error message.

  test = null' [ ]

      Ambiguous type variable `a' in the constraint:
           `Eq a' arising from a use of `null'' at null.hs:6:17-24
         Probable fix: add a type signature that fixes these type
variable(s)

Why is that? And how can it be fixed?  I know I can fix it as follows.

  test = null' ([ ] :: [Integer])

  > :reload
  > test
  True

That's what suggested to me that [ ] had to be compiled into a concrete
value.


It seemed to me that similar reasoning applied to things like 1.  How is the
following explained?

   Prelude> 111111111111111111111111111111111111111111
   111111111111111111111111111111111111111111
   it :: (Num t) => t
   Prelude> maxBound :: Int
   2147483647
   it :: Int
   Prelude> 111111111111111111111111111111111111111111 - (1::Int)
   -954437178
   it :: Int

Does it make sense to say that the long string of 1's is really of type (Num
t) => t?

If so, what does the compiler think it's doing when it processes(?) it as an
Int so that it can subtract 1 :: Int from it?  It didn't treat it as
maxBound :: Int.  And yet it didn't generate an error message.

Thanks

-- Russ
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20101001/e9fb2524/attachment-0001.html


More information about the Beginners mailing list