[Haskell-beginners] fromIntegral

Daniel Fischer daniel.is.fischer at web.de
Sat Oct 2 18:56:48 EDT 2010


On Saturday 02 October 2010 23:28:59, Thomas wrote:
> So, instantiating Char for Num would require you to provide
> implementations for (+), (*), (-), negate, abs, signum and fromInteger
> for Char.
> While syntactically possible, I don't see any semantically reasonable
> way to do so.
>

For some values of reasonable, defining the operations via the Enum 
instance is semantically reasonable.

It's however not the best approach, even if for some odd reason you need 
21-bit integers.

> > Is there a way to display a value along with its type during program
> > execution?  I know about Show; is there something similar like
> > ShowWithType (or even ShowType) that (if implemented) will generate a
> > string of a value along with its type?
>
> AFAIK in GHCi you can do both, but not simultaneously:
> Prelude> let a = 5::Int
> Prelude> :t a
> a :: Int
> Prelude> a
> 5
>

:set +t

makes ghci display the type of an expression entered at the prompt (except 
if it's an IO-action, then it behaves a little different).

> > It makes sense to me to say that [ ] is a function that takes a type
> > as an argument and generates an value. If that's the case, it also
> > makes sense to say that [ ] == [ ] can't be evaluated because there is
> > simply no == for functions.
>
> Prelude> :t []
> [] :: [a]
>
> So [] is a list type, not a function type.
>

Right. [] as a function taking a type as argument is how it's represented 
at the Core level in GHC, not how it's understood at the Haskell level or 
the assembly level.

> Prelude> [] == []
> True
>
> You can actually compare [] to itself.

At the ghci prompt, since that uses extended default rules and chooses to 
compare at the type [()]. In a source file, you'd have to turn on the 
extended default rules ({-# LANGUAGE ExtendedDefaultRules #-}) or tell the 
compiler which type to use.

>
>
> So your reasoning does not seem to be valid to me.
> At least not on the Haskell source code level (which is what you and
> your students work with). Daniel referred to the Core level when saying
> that [] was a function there.
>
>
> My reasoning would go somewhere along the following line:
> [] has a polymorphic type, specifically it's an empty list of elements
> of any type ([] :: [a], type variable a is not restricted)
>
> So, [] will compare to any empty list, no matter what its elements' type
> actually is.

You need an Eq instance, of course.

>
> Given:
>  > let
>  >	xs = []
>  >       ys = 1:xs
>  >       zs = 'a': xs
>
> Then "tail ys == tail zs" will not type check. Neither "tail ys" nor
> "tail zs" are polymorphic:
> ys :: [Integer]

Well, tail ys is polymorphic, its type is

tail ys :: Num a => [a]

the type variable a is defaulted to Integer if there are no further 
constraints on a. If you use it for other stuff, it can be used at other 
types too.

Prelude> let xs = []; ys = 1:xs; ws = length xs:tail ys; vs = pi:tail ys in 
(tail ws, tail vs)
([],[])
it :: (Floating a) => ([Int], [a])

> zs :: [Char]
>
> So the expression "tail ys == tail zs" is invalid - the lhs and rhs must
> have the same type but they do not. Nothing will get compared, no tail
> will be determined - it will just plainly be rejected from the compiler
> (or interpreter).
>
> For comparison: "tail ys == []" is different.
> (tail ys) :: [Integer]
> [] :: [a]
>
> So we set (well, GHC does this for us) type variable a to Integer and
> have: tail ys :: [Integer] == [] :: [Integer]
> which is perfectly valid.
>

Yep.

> > It also makes sense to me to say that == is a collection of more
> > concrete functions from which one is selected depending on the type
> > required by the expression within which == appears.
>
> See above - [] is not a function.
>
> > Since the required type is known at compile time, it would seem that
> > the selection of which == to use could be made at compile time. One
> > shouldn't have to carry along a dictionary.  (Perhaps someone said
> > that earlier. But if so, why the long discussion about Dictionaries?)
> > This seems like a standard definition of an overloaded function.  So
> > why is there an objection to simply saying that == is overloaded and
> > letting it go at that?
>
> (==) :: (Eq a) => a -> a -> Bool
>
> So, yes, (==) feels a little like an overloaded function.

And such functions are often called overloaded.

> It is a function that accepts any Eq-comparable type.
> However, overloading IIRC does not behave identically.

Overloading in Java, C# etc. behaves differently. Overloading is still a 
good term to describe (==) etc. in my opinion. One has to be aware that the 
word denotes different though related concepts for different languages, of 
course.

> For example function arity is not required to be the same when
> overloading methods - and restrictions on types are very different, too.
>
> HTH,
> Thomas


More information about the Beginners mailing list