ais
ais

Reputation: 2624

How can I create an array with polymorphic data?

I am trying to do this

data Foo a = Foo a
data FooWrapper = FooWrapper (forall a. Foo a)

foo = [FooWrapper (Foo 0), FooWrapper (Foo "")]

But there is an error

Could not match type

Int

with type

a0

Upvotes: 0

Views: 299

Answers (2)

frabbit
frabbit

Reputation: 33

I wanted to know how Phil Freeman's suggested approach works, so I gave it a try. This is a working example of storing a type class instance with its value by using a rank-n type.

module Example where

import Prelude (class Show, Unit, discard, pure, show, unit, ($))

import Effect (Effect)
import Effect.Console (log)


newtype Showable = Showable (forall r. (forall a. Show a => a -> r) -> r)

instance showShowable :: Show Showable where
  show (Showable f) = f show

mkShowable :: forall s . Show s => s -> Showable
mkShowable s = Showable (\f -> f s)

showables :: Array Showable
showables = [mkShowable 1, mkShowable "a string", mkShowable { foo : "bar" } ]

main :: Effect Unit
main = do
  log $ show showables
  pure unit

The newtype is not really necessary for storing, but i wanted to create an instance of Show for the type itself .

Upvotes: 0

gb.
gb.

Reputation: 4659

Existential types don't quite work the same in PureScript as they do in Haskell, so usually we use the purescript-exists library for this kind of thing.

The equivalent using Exists would be:

import Data.Exists (Exists(), mkExists)

data Foo a = Foo a
data FooWrapper = FooWrapper (Exists Foo)

foo = [FooWrapper (mkExists (Foo 0)), FooWrapper (mkExists (Foo ""))]

I suppose in this case you probably don't need FooWrapper at all and could just have an array of Exists Foo.

Upvotes: 1

Related Questions