I need to define a Union Type which the set of the type includes
a -> b OR a -> IO b
a -> b || a -> IO b
or
a -> b | IO b
foo :: (a -> b | IO b) -> IO (R a) -> IO (R b)
I tried data unionType b = b | IO b that does not work.
Not a data constructor: ‘b’parser
No quick fixes available
Is it possible in Haskell?
CodePudding user response:
In Haskell, a sum type (the standard term for a disjoint union type) requires explicit "constructors" for its components, so you need to write something like:
data BarType b = BarPure b | BarIO (IO b)
This defines a type BarType, and it also defines constructors BarPure and BarIO for use in constructing values of this type:
val1, val2 :: BarType String
val1 = BarPure "pure"
val2 = BarIO getLine
and consuming values of this type via case-matching:
runBar :: BarType b -> IO b
runBar barb = case barb of
BarPure s -> pure s
BarIO act -> act
CodePudding user response:
There are two issues: On the one hand your type must be upper-case, that is UnionType. Second, you need to define type constructors to be able to create a value of said data type. So the closest would be e.g.
data UnionType b = Left b | Right (IO b)
Here I chose the arbitrary names Left and Right for the constructors, but you can use any you like.
If the Left/Right constructors seem familiar to you, that is because Either uses these by default, and can do exactly the same with a slightly "cheaper" type synonym:
type UnionType b = Either b (IO b)
Of course in both cases we have to deconstruct the type to get to the actual values of b and IO b.
EDIT: As @leftroundabout mentioned, it is not very convenient to define a data type with type constructors called Left and Right, as these constructors are already used with the built in Either.
