How do I make an heterogeneous list in Haskell? (originally in Java)

前端 未结 4 1671
南旧
南旧 2021-02-10 13:13

How to convert following Java implementation into Haskell?

The major purpose here is having a list that contains various elements which are sub-type of a particular in

4条回答
  •  無奈伤痛
    2021-02-10 13:40

    This is possible but probably not desirable. There is such language extension as 'existential types' that allows dynamic polymorphism.

    The idea of existential type is following:

    data Foo = Foo a
    

    Note that type variable "a" doesn't appear on the left side of ADT declaration. Simple example of possible implementation of dynamic polymorphic list and map function:

    {-# LANGUAGE UnicodeSyntax, Rank2Types, GADTs, ConstraintKinds #-}
    
    import Data.Constraint
    
    -- List datatype:
    data PList α where
       Nil  ∷ PList α
       (:*) ∷ α a ⇒ a → PList α → PList α
    
    infixr 6 :*
    
    -- Polymorphic map:
    pmap ∷ (∀ a. α a ⇒ a → b) → PList α → [b]
    pmap _ Nil      = []
    pmap f (a :* t) = f a : pmap f t
    
    main = let
            -- Declare list of arbitrary typed values with overloaded instance Show:
            l ∷ PList Show
            l = "Truly polymorphic list " :* 'a' :* 1 :* (2, 2) :* Nil
        in do
            -- Map show to list:
            print $ pmap show l
    

    Output:

    ["\"Truly polymorphic list \"","'a'","1","(2,2)"]
    

    Another example using this technique:

    class Show a ⇒ Named a where
        name ∷ a → String
    
    instance Named Int where
        name a = "I'm Int and my value is " ++ show a
    
    instance Named Char where
        name a = "I'm Char and my value is " ++ show a
    
     main = let
            -- Declare list of arbitrary typed values with overloaded instance Named:
            l2 :: PList Named
            l2 = 'a' :* (1 ∷ Int) :* Nil
        in do 
            print $ pmap name l2
            print $ pmap show l2
    

    Output:

    ["I'm Char and my value is 'a'","I'm Int and my value is 1"]
    ["'a'","1"]
    

提交回复
热议问题