haskell polymorphism and lists

后端 未结 6 1010
温柔的废话
温柔的废话 2021-02-02 13:45

Suppose I have the following:

class Shape a where
    draw a :: a -> IO ()

data Rectangle = Rectangle Int Int

instance Shape Rectangle where
    draw (Recta         


        
6条回答
  •  难免孤独
    2021-02-02 14:29

    If you really do need to do this, then use an existential:

    {-# LANGUAGE GADTs #-}
    
    
    class IsShape a where
        draw :: a -> IO ()
    
    data Rectangle = Rectangle Int Int
    
    instance IsShape Rectangle where
        draw (Rectangle length width) = ...
    
    data Circle = Circle Int Int
    
    instance IsShape Circle where
        draw (Circle center radius) = ...
    
    data Shape where
        Shape :: IsShape a => a -> Shape
    
    shapes = [Shape (Circle 5 10), Shape (Circle 20 30), Shape (Rectangle 10 15)]
    

    (I renamed your class as there would be a name clash with the datatype otherwise, and having the naming this way round seems more natural).

    The advantage of this solution over the other answer involving a single datatype with different constructors is that it is open; you can define new instances of IsShape wherever you like. The advantage of the other answer is that it's more "functional", and also that the closedness may in some cases be an advantage as it means that clients know exactly what to expect.

提交回复
热议问题