Haskell supports type classes, like equality:
class Eq a where
(==) :: a -> a -> Bool
Rust does the same with type traits:
pub trait Draw {
fn draw(&self);
}
Now, it's possible to declare in Haskell a list whose elements must belong to the equality type class: Eq a => [a] (I believe a is called a constrained type in Haskell). However, the elements of the list still must all be the same type! Say, all Integer or all Float or something. In Rust, however, one can have a list (a vector) of values where each implements a given trait but they are not necessarily the same concrete type: Vec<Box<dyn Draw>>. Is there a way to do the same in Haskell? Like, I want a list of values but all I care about is that each belong to some type class but not necessarily the same concrete type.
In Haskell, you can use existential types to express "some unknown type of this typeclass". (In older versions of GHC, you will need a few standard extensions on.)
class Draw a where
-- whatever the methods are
data SomeDraw where
SD :: Draw a => a -> SomeDraw
type MyList = [SomeDraw]
However, note that this is often overkill, and leads to a known anti-pattern.
For instance, if we had a class as follows:
class Draw a where
draw :: a -> String
then the type MyList above is isomorphic to [String] (or at least morally such). There is no advantage to store an unknown "drawable" object whose only method converts it to string compared to storing the string directly. Also note that Haskell is lazy, so you can "store a string which is not evaluated yet", so to speak.
Anyway, existential quantification on typeclasses can also be defined in a generic way:
import Data.Kind
-- Ex has the same role of "dyn" in Rust here
data Ex (c :: Type -> Constraint) where
Ex :: c a => a -> Ex c
type MyList = [Ex Draw]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With