Two Questions... 
Author Message
 Two Questions...

Hi!

Can anyone help me with these questions?

1)      Some time ago a read an article that outlined the increases
        in efficiency of functional language implementations.
        This showed an efficiency increase of a few orders of magnitude
        from SASL to LML.
        Unfortunately, I can't remember the title of the paper or
        its author;  does anyone know what this paper was?
        I'm not sure what journal it was in either. (LNCS? LISP and FP Conf?)

2)      Why can Haskell constructor functions not be overloaded?
        Is there a good theoretical reason for this? I've found
        quite a number of times that this would be useful.
        And afterall, numbers can be overloaded and you might view
        them simply as a (big!) enumeration.

Many thanks,

        Bert.

-----------------------------------------------------------------------

department of computer science                  university of melbourne
-----------------------------------------------------------------------
                        g e t  t h e  p o i n t
-----------------------------------------------------------------------



Mon, 22 Jan 1996 10:37:52 GMT  
 Two Questions...

Quote:

> 1) Some time ago a read an article that outlined the increases
>    in efficiency of functional language implementations.
>    This showed an efficiency increase of a few orders of magnitude
>    from SASL to LML.
>    Unfortunately, I can't remember the title of the paper or
>    its author;  does anyone know what this paper was?
>    I'm not sure what journal it was in either. (LNCS? LISP and FP Conf?)

Sorry, I can't help on that one. Let me know if you find out.

Quote:
> 2) Why can Haskell constructor functions not be overloaded?

They can. As an example, take the constructor (:+) which makes complex
numbers. It's defined by

data (RealFloat a) => Complex  a = a :+ a

and is therefore overloaded for Float and Double and any other type you
care to give RealFloat instances for.

--

Tony Davie               Department of Mathematical and Computational
Sciences
Tel: +44 334 63257       St.Andrews University
Fax: +44 334 63278       North Haugh

                         Scotland
                         KY16 9SS



Tue, 23 Jan 1996 22:03:26 GMT  
 Two Questions...
In comp.lang.functional you write:


|> 2)   Why can Haskell constructor functions not be overloaded?

|They can. As an example, take the constructor (:+) which makes complex
|numbers. It's defined by

|data (RealFloat a) => Complex  a = a :+ a

|and is therefore overloaded for Float and Double and any other type you
|care to give RealFloat instances for.

This wasn't what I meant. I should've been clearer.

Why is the following not reasonable?

--------------------
class Zilch a where
        Zero :: a

instance Zilch Float where
        Zero = 0.0

instance Zilch Int where
        Zero = 0

is_zero :: (Zilch a) => a -> Bool
is_zero Zero = True
is_zero other = False
--------------------

As an example of why this might be useful...
Let's say I'm dealing with some splay trees and some other binary trees.
(Please forgive the factitiousness of the example, but I really did
think of this when doing AVL- and Splay-tree hacking.)

--------------------
-- THE WAY IT IS.
data SplayTree a = SNil | STree (SplayTree a) a (SplayTree a)
data BinTree a = BNil | BTree (BinTree a) a (BinTree a)

class (BinaryTree tree) where
        left :: tree a -> tree a
        right :: tree a -> tree a
        is_empty :: tree a -> Bool

instance (BinaryTree SplayTree) where
        left (STree left root right) = left
        right (STree left root right) = right
        is_empty SNil = True
        is_empty (STree _ _ _) = False

instance (BinaryTree BinTree) where
        left (BTree left root right) = left
        right (BTree left root right) = right
        is_empty BNil = True
        is_empty (BTree _ _ _) = False

depth :: (BinaryTree tree) => tree a -> Int
depth tree
        | is_empty tree =
                0
        | otherwise =
                1 + max (depth (left tree)) (depth (right tree))

--------------------
-- THE WAY IT MIGHT BE.

class BinaryTree tree where
        Nil :: tree a
        Tree :: tree a -> a -> tree a -> tree a

instance BinaryTree SplayTree where
        Nil = SNil
        Tree = STree
instance BinaryTree BinTree where
        Nil = BNil
        Tree = BTree

-- or maybe just:
-- instance BinaryTree SplayTree
-- instance BinaryTree BinTree

depth :: (BinaryTree tree) => tree a -> Int
depth_tree Nil = 0
depth_tree (Tree left root right) =
        1 + max (depth left) (depth right)

-- You keep the benefits of pattern-matching, too.
--------------------

Hope this is clearer.

Anyone know a good reason why this couldn't or shouldn't be done?

As I said before; if you view the Haskell numbers 1,2,3,4,... as just a big
enumeration, then they are effectively overloaded nullary constructor
functions.

instance Num Integer where
        0 :: Int
        1 :: Int
        ...

instance Num Float where
        0 :: Float
        1 :: Float
        ...

1 :: (Num a) => a

        Bert.

-----------------------------------------------------------------------

department of computer science                  university of melbourne
-----------------------------------------------------------------------



Sun, 28 Jan 1996 14:45:43 GMT  
 Two Questions...

Quote:

>Anyone know a good reason why this couldn't or shouldn't be done?

For enumerations, I don't think there's a big problem.  By analogy with
numeric constants:

        class Eq a => Numbers a where
                One, Two, Three :: a

        instance Numbers Int where
                One = 1
                Two = 2
                Three = 3

        f One = Two
        f Two = Three
        f Three = One

==>  data Numbers = One | Two | Three deriving Eq

        fromNumbers f = f

        fromNumbers.Int One = 1
        fromNumbers.Int Two = 2
        fromNumbers.Int Three = 3

        dict.Numbers.Int x = (fromNumbers.Int x,...,eq.==.Int,...)

        f da db x | da.== x fromNumbers da One =   fromNumbers db Two
                  | da.== x fromNumbers da Two =   fromNumbers db Three
                  | da.== x fromNumbers da Three = fromNumbers db One
                  where da.== (_,...,(==),...) = (==)

Compared with standard Haskell, it's a little extra work to implement
(you'd need to special case non-numeric nullary constructors, and
introduce the data declaration or its equivalent).  Note that you need
equality to be defined for this implementation to work, and that the
inferred type for f is f :: (Numbers a, Numbers b) => a -> b, perhaps
not what you'd expect.  If you did implement this, you would probably
also want defaults to apply to non-numeric types (this simplifies the
implementation slightly since you no longer need to check that all
defaulting classes are numeric).

General data types (with non-nullary constructors) are a different issue.
I haven't been able to work out a good implementation for these.

As to why we don't have overloaded non-numeric constants, Haskell 1
was supposed to be a conservative design.  If overloaded constants
turn out to be highly useful, then they should certainly be considered
for Haskell 2.

Kevin
--

This Signature Intentionally segmentation fault



Mon, 29 Jan 1996 05:01:47 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. Two questions regarding J's syntax and semantics

2. two questions RB & MacOs

3. Two Questions

4. Two Questions About Squeak

5. Two questions about Windows Applications

6. Two questions about default buttons...

7. Two questions

8. Two questions C5.0b

9. Two questions

10. Two Questions

11. Two questions about compiling/linking

12. Two Questions.

 

 
Powered by phpBB® Forum Software