unison/docs/type-declarations.markdown
2018-11-20 18:15:07 -05:00

2.4 KiB

draft draft draft

Type Declarations in Unison

Structural Types

Structural types are defined uniquely by their structure. For example, the following types are identical and interoperable:

structural Maybe a = Nothing | Just a
structural Optional t = Some t | None

The identity of a structural type is determined by sorting the constructors .

Nominal Types

note: https://en.wikipedia.org/wiki/Contrast_set

Alternative 1

Nominal types are defined by a GUID generated at the time they are added to a codebase. They are not interoperable with any other type.

Question: Does this mean that an identically named type with identical contents aded by two people, or added by the same person on different days are totally unrelated? This seems unfortunate, but maybe unavoidable under this model.

Alternative 2

A nominal type is defined by a hash of its constructors, which are indexed by name; e.g. the following types are identical:

nominal Tint a = Red | Green | Blue | Other a
nominal Hue b = Blue | Green | Red | Other b

and these two values are the same:

x = Tint.Red
y = Hue.Red

Arya: Might be a good idea to newtype these for different application contexts, to help in later refactoring e.g.:

nominal Color = Red | Green | Blue
nominal MainLamp = MainLamp Color
nominal SideLamp = SideLamp Color

This way, if Color is updated to include a Color.Yellow constructor, you can opt in to the update independently for MainLamp vs SideLamp usage sites, rather than having to more deeply understand the code around each Color type usage to opt in or out of the upgrade.

Opaque Types

ehh these are like newtypes but with associated definitions that can see through the newtype

opaque type Tagged s t = s where
  tag :: s -> Tagged s t
  tag s = s
  untag :: Tagged s t -> s
  untag st = st
  deepTag :: f s -> f (Tagged s t)
  deepTag fs  = fs
  deepUntag :: f (Tagged s t) -> f s
  deepUntag fst = fst

Algebraic Types

Algebraic types are defined by their structure and a set of laws relating their fields. Note that the laws may involve more than one type.

algebraic Monoid a = Monoid { mempty : a, mappend : a -> a -> a }
where m a -> (mappend m) (mempty m) a == a
      m a -> (mappend m) a (mempty m) == a
      m a b c -> (mappend m) a ((mappend m) b c) ==
                 (mappend m) ((mappend m) a b) c