[Haskell-beginners] fromIntegral

Felipe Lessa felipe.lessa at gmail.com
Fri Oct 1 01:25:42 EDT 2010


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.

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

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.

> 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.

--

I think it's correct to say that in the very end you have to pick
all the types of your program.  However, that choice may be left
until the very very end: until the moment that 'main :: IO ()' is
compiled.

For example, Data.Map functions are all polymorphic.  In fact,
most, if not all, functions in 'containers' package are
polymorphic.  Yet we can compile that package just fine.

--

I think you may be mistaking the optimizer for the whole thing.
It is possible to compile optimized versions of all polymorphic
functions specializing them to specific choices of types.  We
even have the SPECIALIZE pragma.  However, polymorphic functions
don't *need* to specialized and can be compiled without knowing
what are the specific types at all.  If that's efficient or not,
that's beside point.

Cheers! =)

--
Felipe.


More information about the Beginners mailing list