How to model class hierarchies in Haskell?

前端 未结 4 1832
傲寒
傲寒 2021-02-04 05:33

I am a C# developer. Coming from OO side of the world, I start with thinking in terms of interfaces, classes and type hierarchies. Because of lack of OO in Haskell, sometimes I

4条回答
  •  名媛妹妹
    2021-02-04 06:18

    Let's assume the following operations: Humans can speak, Dogs can bark, and all members of a species can mate with members of the same species if they have opposite gender. I would define this in haskell like this:

    data Gender = Male | Female deriving Eq
    
    class Species s where
        gender :: s -> Gender
    
    -- Returns true if s1 and s2 can conceive offspring
    matable :: Species a => a -> a -> Bool
    matable s1 s2 = gender s1 /= gender s2
    
    data Human = Man | Woman
    data Canine = Dog | Bitch
    
    instance Species Human where
        gender Man = Male
        gender Woman = Female
    
    instance Species Canine where
        gender Dog = Male
        gender Bitch = Female
    
    bark Dog = "woof"
    bark Bitch = "wow"
    
    speak Man s = "The man says " ++ s
    speak Woman s = "The woman says " ++ s
    

    Now the operation matable has type Species s => s -> s -> Bool, bark has type Canine -> String and speak has type Human -> String -> String.

    I don't know whether this helps, but given the rather abstract nature of the question, that's the best I could come up with.

    Edit: In response to Daniel's comment:

    A simple hierarchy for collections could look like this (ignoring already existing classes like Foldable and Functor):

    class Foldable f where
        fold :: (a -> b -> a) -> a -> f b -> a
    
    class Foldable m => Collection m where
        cmap :: (a -> b) -> m a -> m b
        cfilter :: (a -> Bool) -> m a -> m a
    
    class Indexable i where
        atIndex :: i a -> Int -> a
    
    instance Foldable [] where
        fold = foldl
    
    instance Collection [] where
        cmap = map
        cfilter = filter
    
    instance Indexable [] where
        atIndex = (!!)
    
    sumOfEvenElements :: (Integral a, Collection c) => c a -> a
    sumOfEvenElements c = fold (+) 0 (cfilter even c)
    

    Now sumOfEvenElements takes any kind of collection of integrals and returns the sum of all even elements of that collection.

提交回复
热议问题