diff --git a/src/Control/Applicative.purs b/src/Control/Applicative.purs index d4c8489c..da24dd45 100644 --- a/src/Control/Applicative.purs +++ b/src/Control/Applicative.purs @@ -10,6 +10,7 @@ import Control.Apply (class Apply, apply, (*>), (<*), (<*>)) import Data.Functor (class Functor, map, void, ($>), (<#>), (<$), (<$>)) import Data.Unit (Unit, unit) +import Type.Proxy (Proxy(..)) -- | The `Applicative` type class extends the [`Apply`](#apply) type class -- | with a `pure` function, which can be used to create values of type `f a` @@ -38,6 +39,9 @@ instance applicativeFn :: Applicative ((->) r) where instance applicativeArray :: Applicative Array where pure x = [x] +instance applicativeProxy :: Applicative Proxy where + pure _ = Proxy + -- | `liftA1` provides a default implementation of `(<$>)` for any -- | [`Applicative`](#applicative) functor, without using `(<$>)` as provided -- | by the [`Functor`](#functor)-[`Applicative`](#applicative) superclass diff --git a/src/Control/Apply.purs b/src/Control/Apply.purs index fba309a6..0cc90dd8 100644 --- a/src/Control/Apply.purs +++ b/src/Control/Apply.purs @@ -9,6 +9,7 @@ module Control.Apply import Data.Functor (class Functor, map, void, ($>), (<#>), (<$), (<$>)) import Data.Function (const) import Control.Category (identity) +import Type.Proxy (Proxy(..)) -- | The `Apply` class provides the `(<*>)` which is used to apply a function -- | to an argument under a type constructor. @@ -54,6 +55,9 @@ instance applyArray :: Apply Array where foreign import arrayApply :: forall a b. Array (a -> b) -> Array a -> Array b +instance applyProxy :: Apply Proxy where + apply _ _ = Proxy + -- | Combine two effectful actions, keeping only the result of the first. applyFirst :: forall a b f. Apply f => f a -> f b -> f a applyFirst a b = const <$> a <*> b diff --git a/src/Control/Bind.purs b/src/Control/Bind.purs index 6d7c145d..3d4476f1 100644 --- a/src/Control/Bind.purs +++ b/src/Control/Bind.purs @@ -19,6 +19,7 @@ import Control.Category (identity) import Data.Function (flip) import Data.Functor (class Functor, map, void, ($>), (<#>), (<$), (<$>)) import Data.Unit (Unit) +import Type.Proxy (Proxy(..), Proxy2, Proxy3) -- | The `Bind` type class extends the [`Apply`](#apply) type class with a -- | "bind" operation `(>>=)` which composes computations in sequence, using @@ -90,6 +91,9 @@ instance bindArray :: Bind Array where foreign import arrayBind :: forall a b. Array a -> (a -> Array b) -> Array b +instance bindProxy :: Bind Proxy where + bind _ _ = Proxy + -- | A class for types whose values can safely be discarded -- | in a `do` notation block. -- | @@ -101,6 +105,15 @@ class Discard a where instance discardUnit :: Discard Unit where discard = bind +instance discardProxy :: Discard (Proxy a) where + discard = bind + +instance discardProxy2 :: Discard (Proxy2 a) where + discard = bind + +instance discardProxy3 :: Discard (Proxy3 a) where + discard = bind + -- | Collapse two applications of a monadic type constructor into one. join :: forall a m. Bind m => m (m a) -> m a join m = m >>= identity diff --git a/src/Control/Monad.purs b/src/Control/Monad.purs index 7b1d9228..6923e637 100644 --- a/src/Control/Monad.purs +++ b/src/Control/Monad.purs @@ -15,6 +15,7 @@ import Control.Bind (class Bind, bind, ap, ifM, join, (<=<), (=<<), (>=>), (>>=) import Data.Functor (class Functor, map, void, ($>), (<#>), (<$), (<$>)) import Data.Unit (Unit) +import Type.Proxy (Proxy) -- | The `Monad` type class combines the operations of the `Bind` and -- | `Applicative` type classes. Therefore, `Monad` instances represent type @@ -32,6 +33,8 @@ instance monadFn :: Monad ((->) r) instance monadArray :: Monad Array +instance monadProxy :: Monad Proxy + -- | `liftM1` provides a default implementation of `(<$>)` for any -- | [`Monad`](#monad), without using `(<$>)` as provided by the -- | [`Functor`](#functor)-[`Monad`](#monad) superclass relationship. diff --git a/src/Data/BooleanAlgebra.purs b/src/Data/BooleanAlgebra.purs index 44a6c184..acc3617e 100644 --- a/src/Data/BooleanAlgebra.purs +++ b/src/Data/BooleanAlgebra.purs @@ -9,6 +9,7 @@ import Data.Symbol (class IsSymbol) import Data.Unit (Unit) import Prim.Row as Row import Prim.RowList as RL +import Type.Proxy (Proxy, Proxy2, Proxy3) -- | The `BooleanAlgebra` type class represents types that behave like boolean -- | values. @@ -24,9 +25,13 @@ instance booleanAlgebraBoolean :: BooleanAlgebra Boolean instance booleanAlgebraUnit :: BooleanAlgebra Unit instance booleanAlgebraFn :: BooleanAlgebra b => BooleanAlgebra (a -> b) instance booleanAlgebraRecord :: (RL.RowToList row list, BooleanAlgebraRecord list row row) => BooleanAlgebra (Record row) +instance booleanAlgebraProxy :: BooleanAlgebra (Proxy a) +instance booleanAlgebraProxy2 :: BooleanAlgebra (Proxy2 a) +instance booleanAlgebraProxy3 :: BooleanAlgebra (Proxy3 a) -- | A class for records where all fields have `BooleanAlgebra` instances, used -- | to implement the `BooleanAlgebra` instance for records. +class BooleanAlgebraRecord :: RL.RowList Type -> Row Type -> Row Type -> Constraint class HeytingAlgebraRecord rowlist row subrow <= BooleanAlgebraRecord rowlist row subrow | rowlist -> subrow instance booleanAlgebraRecordNil :: BooleanAlgebraRecord RL.Nil row () diff --git a/src/Data/Bounded.purs b/src/Data/Bounded.purs index acfe6f70..d28fe45e 100644 --- a/src/Data/Bounded.purs +++ b/src/Data/Bounded.purs @@ -7,13 +7,12 @@ module Data.Bounded ) where import Data.Ord (class Ord, class OrdRecord, Ordering(..), compare, (<), (<=), (>), (>=)) -import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) import Data.Unit (Unit, unit) import Prim.Row as Row import Prim.RowList as RL import Record.Unsafe (unsafeSet) -import Type.Data.Row (RProxy(..)) -import Type.Data.RowList (RLProxy(..)) +import Type.Proxy (Proxy(..), Proxy2(..), Proxy3(..)) -- | The `Bounded` type class represents totally ordered types that have an -- | upper and lower boundary. @@ -62,9 +61,22 @@ instance boundedNumber :: Bounded Number where top = topNumber bottom = bottomNumber +instance boundedProxy :: Bounded (Proxy a) where + bottom = Proxy + top = Proxy + +instance boundedProxy2 :: Bounded (Proxy2 a) where + bottom = Proxy2 + top = Proxy2 + +instance boundedProxy3 :: Bounded (Proxy3 a) where + bottom = Proxy3 + top = Proxy3 + +class BoundedRecord :: RL.RowList Type -> Row Type -> Row Type -> Constraint class OrdRecord rowlist row <= BoundedRecord rowlist row subrow | rowlist -> subrow where - topRecord :: RLProxy rowlist -> RProxy row -> Record subrow - bottomRecord :: RLProxy rowlist -> RProxy row -> Record subrow + topRecord :: forall rlproxy rproxy. rlproxy rowlist -> rproxy row -> Record subrow + bottomRecord :: forall rlproxy rproxy. rlproxy rowlist -> rproxy row -> Record subrow instance boundedRecordNil :: BoundedRecord RL.Nil row () where topRecord _ _ = {} @@ -81,21 +93,21 @@ instance boundedRecordCons topRecord _ rowProxy = insert top tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - tail = topRecord (RLProxy :: RLProxy rowlistTail) rowProxy + tail = topRecord (Proxy :: Proxy rowlistTail) rowProxy bottomRecord _ rowProxy = insert bottom tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - tail = bottomRecord (RLProxy :: RLProxy rowlistTail) rowProxy + tail = bottomRecord (Proxy :: Proxy rowlistTail) rowProxy instance boundedRecord :: ( RL.RowToList row list , BoundedRecord list row row ) => Bounded (Record row) where - top = topRecord (RLProxy :: RLProxy list) (RProxy :: RProxy row) - bottom = bottomRecord (RLProxy :: RLProxy list) (RProxy :: RProxy row) + top = topRecord (Proxy :: Proxy list) (Proxy :: Proxy row) + bottom = bottomRecord (Proxy :: Proxy list) (Proxy :: Proxy row) diff --git a/src/Data/CommutativeRing.purs b/src/Data/CommutativeRing.purs index 6fcf498f..12e8c5d3 100644 --- a/src/Data/CommutativeRing.purs +++ b/src/Data/CommutativeRing.purs @@ -11,6 +11,7 @@ import Data.Symbol (class IsSymbol) import Data.Unit (Unit) import Prim.Row as Row import Prim.RowList as RL +import Type.Proxy (Proxy, Proxy2, Proxy3) -- | The `CommutativeRing` class is for rings where multiplication is -- | commutative. @@ -26,6 +27,9 @@ instance commutativeRingNumber :: CommutativeRing Number instance commutativeRingUnit :: CommutativeRing Unit instance commutativeRingFn :: CommutativeRing b => CommutativeRing (a -> b) instance commutativeRingRecord :: (RL.RowToList row list, CommutativeRingRecord list row row) => CommutativeRing (Record row) +instance commutativeRingProxy :: CommutativeRing (Proxy a) +instance commutativeRingProxy2 :: CommutativeRing (Proxy2 a) +instance commutativeRingProxy3 :: CommutativeRing (Proxy3 a) -- | A class for records where all fields have `CommutativeRing` instances, used -- | to implement the `CommutativeRing` instance for records. diff --git a/src/Data/Eq.purs b/src/Data/Eq.purs index b60f5749..9452da1f 100644 --- a/src/Data/Eq.purs +++ b/src/Data/Eq.purs @@ -5,13 +5,13 @@ module Data.Eq ) where import Data.HeytingAlgebra ((&&)) -import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) import Data.Unit (Unit) import Data.Void (Void) import Prim.Row as Row import Prim.RowList as RL import Record.Unsafe (unsafeGet) -import Type.Data.RowList (RLProxy(..)) +import Type.Proxy (Proxy(..), Proxy2, Proxy3) -- | The `Eq` type class represents types which support decidable equality. -- | @@ -62,7 +62,16 @@ instance eqArray :: Eq a => Eq (Array a) where eq = eqArrayImpl eq instance eqRec :: (RL.RowToList row list, EqRecord list row) => Eq (Record row) where - eq = eqRecord (RLProxy :: RLProxy list) + eq = eqRecord (Proxy :: Proxy list) + +instance eqProxy :: Eq (Proxy a) where + eq _ _ = true + +instance eqProxy2 :: Eq (Proxy2 a) where + eq _ _ = true + +instance eqProxy3 :: Eq (Proxy3 a) where + eq _ _ = true foreign import eqBooleanImpl :: Boolean -> Boolean -> Boolean foreign import eqIntImpl :: Int -> Int -> Boolean @@ -84,8 +93,9 @@ notEq1 x y = (x `eq1` y) == false -- | A class for records where all fields have `Eq` instances, used to implement -- | the `Eq` instance for records. +class EqRecord :: RL.RowList Type -> Row Type -> Constraint class EqRecord rowlist row where - eqRecord :: RLProxy rowlist -> Record row -> Record row -> Boolean + eqRecord :: forall rlproxy. rlproxy rowlist -> Record row -> Record row -> Boolean instance eqRowNil :: EqRecord RL.Nil row where eqRecord _ _ _ = true @@ -99,6 +109,6 @@ instance eqRowCons => EqRecord (RL.Cons key focus rowlistTail) row where eqRecord _ ra rb = (get ra == get rb) && tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) get = unsafeGet key :: Record row -> focus - tail = eqRecord (RLProxy :: RLProxy rowlistTail) ra rb + tail = eqRecord (Proxy :: Proxy rowlistTail) ra rb diff --git a/src/Data/Functor.purs b/src/Data/Functor.purs index e2754832..3e18df84 100644 --- a/src/Data/Functor.purs +++ b/src/Data/Functor.purs @@ -9,6 +9,7 @@ module Data.Functor import Data.Function (const, compose) import Data.Unit (Unit, unit) +import Type.Proxy (Proxy(..)) -- | A `Functor` is a type constructor which supports a mapping operation -- | `map`. @@ -42,6 +43,9 @@ instance functorFn :: Functor ((->) r) where instance functorArray :: Functor Array where map = arrayMap +instance functorProxy :: Functor Proxy where + map _ _ = Proxy + foreign import arrayMap :: forall a b. (a -> b) -> Array a -> Array b -- | The `void` function is used to ignore the type wrapped by a diff --git a/src/Data/HeytingAlgebra.purs b/src/Data/HeytingAlgebra.purs index 5b6920f1..0d4dca48 100644 --- a/src/Data/HeytingAlgebra.purs +++ b/src/Data/HeytingAlgebra.purs @@ -3,13 +3,12 @@ module Data.HeytingAlgebra , class HeytingAlgebraRecord, ffRecord, ttRecord, impliesRecord, conjRecord, disjRecord, notRecord ) where -import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) import Data.Unit (Unit, unit) import Prim.Row as Row import Prim.RowList as RL import Record.Unsafe (unsafeGet, unsafeSet) -import Type.Data.Row (RProxy(..)) -import Type.Data.RowList (RLProxy(..)) +import Type.Proxy (Proxy(..), Proxy2(..), Proxy3(..)) -- | The `HeytingAlgebra` type class represents types that are bounded lattices with -- | an implication operator such that the following laws hold: @@ -71,13 +70,37 @@ instance heytingAlgebraFunction :: HeytingAlgebra b => HeytingAlgebra (a -> b) w disj f g a = f a || g a not f a = not (f a) +instance heytingAlgebraProxy :: HeytingAlgebra (Proxy a) where + conj _ _ = Proxy + disj _ _ = Proxy + implies _ _ = Proxy + ff = Proxy + not _ = Proxy + tt = Proxy + +instance heytingAlgebraProxy2 :: HeytingAlgebra (Proxy2 a) where + conj _ _ = Proxy2 + disj _ _ = Proxy2 + implies _ _ = Proxy2 + ff = Proxy2 + not _ = Proxy2 + tt = Proxy2 + +instance heytingAlgebraProxy3 :: HeytingAlgebra (Proxy3 a) where + conj _ _ = Proxy3 + disj _ _ = Proxy3 + implies _ _ = Proxy3 + ff = Proxy3 + not _ = Proxy3 + tt = Proxy3 + instance heytingAlgebraRecord :: (RL.RowToList row list, HeytingAlgebraRecord list row row) => HeytingAlgebra (Record row) where - ff = ffRecord (RLProxy :: RLProxy list) (RProxy :: RProxy row) - tt = ttRecord (RLProxy :: RLProxy list) (RProxy :: RProxy row) - conj = conjRecord (RLProxy :: RLProxy list) - disj = disjRecord (RLProxy :: RLProxy list) - implies = impliesRecord (RLProxy :: RLProxy list) - not = notRecord (RLProxy :: RLProxy list) + ff = ffRecord (Proxy :: Proxy list) (Proxy :: Proxy row) + tt = ttRecord (Proxy :: Proxy list) (Proxy :: Proxy row) + conj = conjRecord (Proxy :: Proxy list) + disj = disjRecord (Proxy :: Proxy list) + implies = impliesRecord (Proxy :: Proxy list) + not = notRecord (Proxy :: Proxy list) foreign import boolConj :: Boolean -> Boolean -> Boolean foreign import boolDisj :: Boolean -> Boolean -> Boolean @@ -85,13 +108,14 @@ foreign import boolNot :: Boolean -> Boolean -- | A class for records where all fields have `HeytingAlgebra` instances, used -- | to implement the `HeytingAlgebra` instance for records. +class HeytingAlgebraRecord :: RL.RowList Type -> Row Type -> Row Type -> Constraint class HeytingAlgebraRecord rowlist row subrow | rowlist -> subrow where - ffRecord :: RLProxy rowlist -> RProxy row -> Record subrow - ttRecord :: RLProxy rowlist -> RProxy row -> Record subrow - impliesRecord :: RLProxy rowlist -> Record row -> Record row -> Record subrow - disjRecord :: RLProxy rowlist -> Record row -> Record row -> Record subrow - conjRecord :: RLProxy rowlist -> Record row -> Record row -> Record subrow - notRecord :: RLProxy rowlist -> Record row -> Record subrow + ffRecord :: forall rlproxy rproxy. rlproxy rowlist -> rproxy row -> Record subrow + ttRecord :: forall rlproxy rproxy. rlproxy rowlist -> rproxy row -> Record subrow + impliesRecord :: forall rlproxy. rlproxy rowlist -> Record row -> Record row -> Record subrow + disjRecord :: forall rlproxy. rlproxy rowlist -> Record row -> Record row -> Record subrow + conjRecord :: forall rlproxy. rlproxy rowlist -> Record row -> Record row -> Record subrow + notRecord :: forall rlproxy. rlproxy rowlist -> Record row -> Record subrow instance heytingAlgebraRecordNil :: HeytingAlgebraRecord RL.Nil row () where conjRecord _ _ _ = {} @@ -110,41 +134,41 @@ instance heytingAlgebraRecordCons => HeytingAlgebraRecord (RL.Cons key focus rowlistTail) row subrow where conjRecord _ ra rb = insert (conj (get ra) (get rb)) tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) get = unsafeGet key :: Record row -> focus insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - tail = conjRecord (RLProxy :: RLProxy rowlistTail) ra rb + tail = conjRecord (Proxy :: Proxy rowlistTail) ra rb disjRecord _ ra rb = insert (disj (get ra) (get rb)) tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) get = unsafeGet key :: Record row -> focus insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - tail = disjRecord (RLProxy :: RLProxy rowlistTail) ra rb + tail = disjRecord (Proxy :: Proxy rowlistTail) ra rb impliesRecord _ ra rb = insert (implies (get ra) (get rb)) tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) get = unsafeGet key :: Record row -> focus insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - tail = impliesRecord (RLProxy :: RLProxy rowlistTail) ra rb + tail = impliesRecord (Proxy :: Proxy rowlistTail) ra rb ffRecord _ row = insert ff tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - tail = ffRecord (RLProxy :: RLProxy rowlistTail) row + tail = ffRecord (Proxy :: Proxy rowlistTail) row notRecord _ row = insert (not (get row)) tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) get = unsafeGet key :: Record row -> focus insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - tail = notRecord (RLProxy :: RLProxy rowlistTail) row + tail = notRecord (Proxy :: Proxy rowlistTail) row ttRecord _ row = insert tt tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - tail = ttRecord (RLProxy :: RLProxy rowlistTail) row + tail = ttRecord (Proxy :: Proxy rowlistTail) row diff --git a/src/Data/Monoid.purs b/src/Data/Monoid.purs index 2be6640d..6378bf04 100644 --- a/src/Data/Monoid.purs +++ b/src/Data/Monoid.purs @@ -12,12 +12,12 @@ import Data.EuclideanRing (mod, (/)) import Data.Ord ((<=)) import Data.Ordering (Ordering(..)) import Data.Semigroup (class Semigroup, class SemigroupRecord, (<>)) -import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) import Data.Unit (Unit, unit) import Prim.Row as Row import Prim.RowList as RL import Record.Unsafe (unsafeSet) -import Type.Data.RowList (RLProxy(..)) +import Type.Proxy (Proxy(..)) -- | A `Monoid` is a `Semigroup` with a value `mempty`, which is both a -- | left and right unit for the associative operation `<>`: @@ -60,7 +60,7 @@ instance monoidArray :: Monoid (Array a) where mempty = [] instance monoidRecord :: (RL.RowToList row list, MonoidRecord list row row) => Monoid (Record row) where - mempty = memptyRecord (RLProxy :: RLProxy list) + mempty = memptyRecord (Proxy :: Proxy list) -- | Append a value to itself a certain number of times. For the -- | `Multiplicative` type, and for a non-negative power, this is the same as @@ -89,8 +89,9 @@ guard false _ = mempty -- | A class for records where all fields have `Monoid` instances, used to -- | implement the `Monoid` instance for records. +class MonoidRecord :: RL.RowList Type -> Row Type -> Row Type -> Constraint class SemigroupRecord rowlist row subrow <= MonoidRecord rowlist row subrow | rowlist -> row subrow where - memptyRecord :: RLProxy rowlist -> Record subrow + memptyRecord :: forall rlproxy. rlproxy rowlist -> Record subrow instance monoidRecordNil :: MonoidRecord RL.Nil row () where memptyRecord _ = {} @@ -105,6 +106,6 @@ instance monoidRecordCons memptyRecord _ = insert mempty tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - tail = memptyRecord (RLProxy :: RLProxy rowlistTail) + tail = memptyRecord (Proxy :: Proxy rowlistTail) diff --git a/src/Data/Ord.purs b/src/Data/Ord.purs index 4dbad3af..795e9af3 100644 --- a/src/Data/Ord.purs +++ b/src/Data/Ord.purs @@ -16,7 +16,7 @@ module Data.Ord ) where import Data.Eq (class Eq, class Eq1, class EqRecord, (/=)) -import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) import Data.Ordering (Ordering(..)) import Data.Ring (class Ring, zero, one, negate) import Data.Unit (Unit) @@ -24,7 +24,7 @@ import Data.Void (Void) import Prim.Row as Row import Prim.RowList as RL import Record.Unsafe (unsafeGet) -import Type.Data.RowList (RLProxy(..)) +import Type.Proxy (Proxy(..), Proxy2, Proxy3) -- | The `Ord` type class represents types which support comparisons with a -- | _total order_. @@ -58,6 +58,15 @@ instance ordUnit :: Ord Unit where instance ordVoid :: Ord Void where compare _ _ = EQ +instance ordProxy :: Ord (Proxy a) where + compare _ _ = EQ + +instance ordProxy2 :: Ord (Proxy2 a) where + compare _ _ = EQ + +instance ordProxy3 :: Ord (Proxy3 a) where + compare _ _ = EQ + instance ordArray :: Ord a => Ord (Array a) where compare = \xs ys -> compare 0 (ordArrayImpl toDelta xs ys) where @@ -214,8 +223,9 @@ class Eq1 f <= Ord1 f where instance ord1Array :: Ord1 Array where compare1 = compare +class OrdRecord :: RL.RowList Type -> Row Type -> Constraint class EqRecord rowlist row <= OrdRecord rowlist row where - compareRecord :: RLProxy rowlist -> Record row -> Record row -> Ordering + compareRecord :: forall rlproxy. rlproxy rowlist -> Record row -> Record row -> Ordering instance ordRecordNil :: OrdRecord RL.Nil row where compareRecord _ _ _ = EQ @@ -230,9 +240,9 @@ instance ordRecordCons compareRecord _ ra rb = if left /= EQ then left - else compareRecord (RLProxy :: RLProxy rowlistTail) ra rb + else compareRecord (Proxy :: Proxy rowlistTail) ra rb where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) unsafeGet' = unsafeGet :: String -> Record row -> focus left = unsafeGet' key ra `compare` unsafeGet' key rb @@ -241,5 +251,4 @@ instance ordRecord , OrdRecord list row ) => Ord (Record row) where - compare = compareRecord (RLProxy :: RLProxy list) - + compare = compareRecord (Proxy :: Proxy list) diff --git a/src/Data/Ring.purs b/src/Data/Ring.purs index 1d5ab234..9e1c9184 100644 --- a/src/Data/Ring.purs +++ b/src/Data/Ring.purs @@ -5,12 +5,12 @@ module Data.Ring ) where import Data.Semiring (class Semiring, class SemiringRecord, add, mul, one, zero, (*), (+)) -import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) import Data.Unit (Unit, unit) import Prim.Row as Row import Prim.RowList as RL import Record.Unsafe (unsafeGet, unsafeSet) -import Type.Data.RowList (RLProxy(..)) +import Type.Proxy (Proxy(..), Proxy2(..), Proxy3(..)) -- | The `Ring` class is for types that support addition, multiplication, -- | and subtraction operations. @@ -36,8 +36,17 @@ instance ringUnit :: Ring Unit where instance ringFn :: Ring b => Ring (a -> b) where sub f g x = f x - g x +instance ringProxy :: Ring (Proxy a) where + sub _ _ = Proxy + +instance ringProxy2 :: Ring (Proxy2 a) where + sub _ _ = Proxy2 + +instance ringProxy3 :: Ring (Proxy3 a) where + sub _ _ = Proxy3 + instance ringRecord :: (RL.RowToList row list, RingRecord list row row) => Ring (Record row) where - sub = subRecord (RLProxy :: RLProxy list) + sub = subRecord (Proxy :: Proxy list) -- | `negate x` can be used as a shorthand for `zero - x`. negate :: forall a. Ring a => a -> a @@ -48,8 +57,9 @@ foreign import numSub :: Number -> Number -> Number -- | A class for records where all fields have `Ring` instances, used to -- | implement the `Ring` instance for records. +class RingRecord :: RL.RowList Type -> Row Type -> Row Type -> Constraint class SemiringRecord rowlist row subrow <= RingRecord rowlist row subrow | rowlist -> subrow where - subRecord :: RLProxy rowlist -> Record row -> Record row -> Record subrow + subRecord :: forall rlproxy. rlproxy rowlist -> Record row -> Record row -> Record subrow instance ringRecordNil :: RingRecord RL.Nil row () where subRecord _ _ _ = {} @@ -64,6 +74,6 @@ instance ringRecordCons subRecord _ ra rb = insert (get ra - get rb) tail where insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) get = unsafeGet key :: Record row -> focus - tail = subRecord (RLProxy :: RLProxy rowlistTail) ra rb + tail = subRecord (Proxy :: Proxy rowlistTail) ra rb diff --git a/src/Data/Semigroup.purs b/src/Data/Semigroup.purs index aec1628b..c7ee426b 100644 --- a/src/Data/Semigroup.purs +++ b/src/Data/Semigroup.purs @@ -3,13 +3,13 @@ module Data.Semigroup , class SemigroupRecord, appendRecord ) where -import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) import Data.Unit (Unit, unit) import Data.Void (Void, absurd) import Prim.Row as Row import Prim.RowList as RL import Record.Unsafe (unsafeGet, unsafeSet) -import Type.Data.RowList (RLProxy(..)) +import Type.Proxy (Proxy(..), Proxy2(..), Proxy3(..)) -- | The `Semigroup` type class identifies an associative operation on a type. -- | @@ -48,16 +48,26 @@ instance semigroupFn :: Semigroup s' => Semigroup (s -> s') where instance semigroupArray :: Semigroup (Array a) where append = concatArray +instance semigroupProxy :: Semigroup (Proxy a) where + append _ _ = Proxy + +instance semigroupProxy2 :: Semigroup (Proxy2 a) where + append _ _ = Proxy2 + +instance semigroupProxy3 :: Semigroup (Proxy3 a) where + append _ _ = Proxy3 + instance semigroupRecord :: (RL.RowToList row list, SemigroupRecord list row row) => Semigroup (Record row) where - append = appendRecord (RLProxy :: RLProxy list) + append = appendRecord (Proxy :: Proxy list) foreign import concatString :: String -> String -> String foreign import concatArray :: forall a. Array a -> Array a -> Array a -- | A class for records where all fields have `Semigroup` instances, used to -- | implement the `Semigroup` instance for records. +class SemigroupRecord :: RL.RowList Type -> Row Type -> Row Type -> Constraint class SemigroupRecord rowlist row subrow | rowlist -> subrow where - appendRecord :: RLProxy rowlist -> Record row -> Record row -> Record subrow + appendRecord :: forall rlproxy. rlproxy rowlist -> Record row -> Record row -> Record subrow instance semigroupRecordNil :: SemigroupRecord RL.Nil row () where appendRecord _ _ _ = {} @@ -71,7 +81,7 @@ instance semigroupRecordCons => SemigroupRecord (RL.Cons key focus rowlistTail) row subrow where appendRecord _ ra rb = insert (get ra <> get rb) tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) get = unsafeGet key :: Record row -> focus insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow - tail = appendRecord (RLProxy :: RLProxy rowlistTail) ra rb + tail = appendRecord (Proxy :: Proxy rowlistTail) ra rb diff --git a/src/Data/Semiring.purs b/src/Data/Semiring.purs index e221cf3d..09250d8c 100644 --- a/src/Data/Semiring.purs +++ b/src/Data/Semiring.purs @@ -3,13 +3,12 @@ module Data.Semiring , class SemiringRecord, addRecord, mulRecord, oneRecord, zeroRecord ) where -import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) import Data.Unit (Unit, unit) import Prim.Row as Row import Prim.RowList as RL import Record.Unsafe (unsafeGet, unsafeSet) -import Type.Data.Row (RProxy(..)) -import Type.Data.RowList (RLProxy(..)) +import Type.Proxy (Proxy(..), Proxy2(..), Proxy3(..)) -- | The `Semiring` class is for types that support an addition and -- | multiplication operation. @@ -65,11 +64,29 @@ instance semiringUnit :: Semiring Unit where mul _ _ = unit one = unit +instance semiringProxy :: Semiring (Proxy a) where + add _ _ = Proxy + mul _ _ = Proxy + one = Proxy + zero = Proxy + +instance semiringProxy2 :: Semiring (Proxy2 a) where + add _ _ = Proxy2 + mul _ _ = Proxy2 + one = Proxy2 + zero = Proxy2 + +instance semiringProxy3 :: Semiring (Proxy3 a) where + add _ _ = Proxy3 + mul _ _ = Proxy3 + one = Proxy3 + zero = Proxy3 + instance semiringRecord :: (RL.RowToList row list, SemiringRecord list row row) => Semiring (Record row) where - add = addRecord (RLProxy :: RLProxy list) - mul = mulRecord (RLProxy :: RLProxy list) - one = oneRecord (RLProxy :: RLProxy list) (RProxy :: RProxy row) - zero = zeroRecord (RLProxy :: RLProxy list) (RProxy :: RProxy row) + add = addRecord (Proxy :: Proxy list) + mul = mulRecord (Proxy :: Proxy list) + one = oneRecord (Proxy :: Proxy list) (Proxy :: Proxy row) + zero = zeroRecord (Proxy :: Proxy list) (Proxy :: Proxy row) foreign import intAdd :: Int -> Int -> Int foreign import intMul :: Int -> Int -> Int @@ -78,11 +95,12 @@ foreign import numMul :: Number -> Number -> Number -- | A class for records where all fields have `Semiring` instances, used to -- | implement the `Semiring` instance for records. +class SemiringRecord :: RL.RowList Type -> Row Type -> Row Type -> Constraint class SemiringRecord rowlist row subrow | rowlist -> subrow where - addRecord :: RLProxy rowlist -> Record row -> Record row -> Record subrow - mulRecord :: RLProxy rowlist -> Record row -> Record row -> Record subrow - oneRecord :: RLProxy rowlist -> RProxy row -> Record subrow - zeroRecord :: RLProxy rowlist -> RProxy row -> Record subrow + addRecord :: forall rlproxy. rlproxy rowlist -> Record row -> Record row -> Record subrow + mulRecord :: forall rlproxy. rlproxy rowlist -> Record row -> Record row -> Record subrow + oneRecord :: forall rlproxy rproxy. rlproxy rowlist -> rproxy row -> Record subrow + zeroRecord :: forall rlproxy rproxy. rlproxy rowlist -> rproxy row -> Record subrow instance semiringRecordNil :: SemiringRecord RL.Nil row () where addRecord _ _ _ = {} @@ -99,26 +117,26 @@ instance semiringRecordCons => SemiringRecord (RL.Cons key focus rowlistTail) row subrow where addRecord _ ra rb = insert (get ra + get rb) tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) get = unsafeGet key :: Record row -> focus - tail = addRecord (RLProxy :: RLProxy rowlistTail) ra rb + tail = addRecord (Proxy :: Proxy rowlistTail) ra rb insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow mulRecord _ ra rb = insert (get ra * get rb) tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) get = unsafeGet key :: Record row -> focus - tail = mulRecord (RLProxy :: RLProxy rowlistTail) ra rb + tail = mulRecord (Proxy :: Proxy rowlistTail) ra rb insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow oneRecord _ _ = insert one tail where - key = reflectSymbol (SProxy :: SProxy key) - tail = oneRecord (RLProxy :: RLProxy rowlistTail) (RProxy :: RProxy row) + key = reflectSymbol (Proxy :: Proxy key) + tail = oneRecord (Proxy :: Proxy rowlistTail) (Proxy :: Proxy row) insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow zeroRecord _ _ = insert zero tail where - key = reflectSymbol (SProxy :: SProxy key) - tail = zeroRecord (RLProxy :: RLProxy rowlistTail) (RProxy :: RProxy row) + key = reflectSymbol (Proxy :: Proxy key) + tail = zeroRecord (Proxy :: Proxy rowlistTail) (Proxy :: Proxy row) insert = unsafeSet key :: focus -> Record subrowTail -> Record subrow diff --git a/src/Data/Show.purs b/src/Data/Show.purs index 836a61c9..33442378 100644 --- a/src/Data/Show.purs +++ b/src/Data/Show.purs @@ -3,10 +3,10 @@ module Data.Show , class ShowRecordFields, showRecordFields ) where -import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) import Prim.RowList as RL import Record.Unsafe (unsafeGet) -import Type.Data.RowList (RLProxy(..)) +import Type.Proxy (Proxy(..), Proxy2, Proxy3) -- | The `Show` type class represents those types which can be converted into -- | a human-readable `String` representation. @@ -36,15 +36,25 @@ instance showString :: Show String where instance showArray :: Show a => Show (Array a) where show = showArrayImpl show +instance showProxy :: Show (Proxy a) where + show _ = "Proxy" + +instance showProxy2 :: Show (Proxy2 a) where + show _ = "Proxy2" + +instance showProxy3 :: Show (Proxy3 a) where + show _ = "Proxy3" + instance showRecord :: (RL.RowToList rs ls, ShowRecordFields ls rs) => Show (Record rs) where - show record = case showRecordFields (RLProxy :: RLProxy ls) record of + show record = case showRecordFields (Proxy :: Proxy ls) record of [] -> "{}" fields -> join " " ["{", join ", " fields, "}"] -- | A class for records where all fields have `Show` instances, used to -- | implement the `Show` instance for records. +class ShowRecordFields :: RL.RowList Type -> Row Type -> Constraint class ShowRecordFields rowlist row where - showRecordFields :: RLProxy rowlist -> Record row -> Array String + showRecordFields :: forall rlproxy. rlproxy rowlist -> Record row -> Array String instance showRecordFieldsNil :: ShowRecordFields RL.Nil row where showRecordFields _ _ = [] @@ -58,9 +68,9 @@ instance showRecordFieldsCons showRecordFields _ record = cons (join ": " [ key, show focus ]) tail where - key = reflectSymbol (SProxy :: SProxy key) + key = reflectSymbol (Proxy :: Proxy key) focus = unsafeGet key record :: focus - tail = showRecordFields (RLProxy :: RLProxy rowlistTail) record + tail = showRecordFields (Proxy :: Proxy rowlistTail) record foreign import showIntImpl :: Int -> String foreign import showNumberImpl :: Number -> String diff --git a/src/Data/Symbol.purs b/src/Data/Symbol.purs index bda2cd3e..619b178e 100644 --- a/src/Data/Symbol.purs +++ b/src/Data/Symbol.purs @@ -5,20 +5,30 @@ module Data.Symbol , SProxy(..) ) where +import Type.Proxy (Proxy(..)) + -- | A value-level proxy for a type-level symbol. -data SProxy (sym :: Symbol) = SProxy +-- | **Deprecated as of v0.14.0 PureScript release**: use `Type.Proxy` instead. +data SProxy :: Symbol -> Type +data SProxy sym = SProxy -- | A class for known symbols class IsSymbol (sym :: Symbol) where - reflectSymbol :: SProxy sym -> String + -- Note: Before v0.14.0, we did not have polykinds. Thus, we needed + -- kind-specific proxy types to pass a Symbol around. + -- Once v0.14.0 was released, we could use the kind-generic `Proxy` type + -- instead. However, to reduce code breakage, we're using + -- `forall proxy. proxy sym` here so that `SProxy` code will still compile. + -- When PureScript makes a new breaking release after the v0.14.0 release, + -- this type signature will be updated to `Proxy sym -> String`. + reflectSymbol :: forall proxy. proxy sym -> String -- local definition for use in `reifySymbol` foreign import unsafeCoerce :: forall a b. a -> b -reifySymbol :: forall r. String -> (forall sym. IsSymbol sym => SProxy sym -> r) -> r -reifySymbol s f = coerce f { reflectSymbol: \_ -> s } SProxy where +reifySymbol :: forall proxy r. String -> (forall sym. IsSymbol sym => proxy sym -> r) -> r +reifySymbol s f = coerce f { reflectSymbol: \_ -> s } Proxy where coerce - :: (forall sym1. IsSymbol sym1 => SProxy sym1 -> r) - -> { reflectSymbol :: SProxy "" -> String } -> SProxy "" -> r + :: (forall sym1. IsSymbol sym1 => proxy sym1 -> r) + -> { reflectSymbol :: Proxy "" -> String } -> Proxy "" -> r coerce = unsafeCoerce - diff --git a/src/Type/Data/Row.purs b/src/Type/Data/Row.purs index 774a0290..f3f022c5 100644 --- a/src/Type/Data/Row.purs +++ b/src/Type/Data/Row.purs @@ -3,6 +3,8 @@ module Type.Data.Row where -- | A proxy data type whose type parameter is a type of kind `Row Type` (a row -- | of types). -- | +-- | **Deprecated as of v0.14.0 PureScript release**: use `Type.Proxy` instead. +-- | -- | Commonly used for specialising a function with a quantified type. -- | For example, suppose we have an identity function for records of type: -- | ```purescript @@ -12,9 +14,9 @@ module Type.Data.Row where -- | Then applying this function to an `RProxy` with a specialised type -- | allows us to specify a concrete type for `row`: -- | ```purescript --- | :t recordIdentity (RProxy :: RProxy ( x :: Int, y :: Int )) +-- | :t recordIdentity (Proxy :: Proxy ( x :: Int, y :: Int )) -- | { x :: Int, y :: Int } -> { x :: Int, y :: Int } -- | ``` -- | Here `row` has been specialised to `( x :: Int, y :: Int )`. -data RProxy (row :: Row Type) - = RProxy +data RProxy :: Row Type -> Type +data RProxy row = RProxy diff --git a/src/Type/Data/RowList.purs b/src/Type/Data/RowList.purs index f85f33d2..21bd48af 100644 --- a/src/Type/Data/RowList.purs +++ b/src/Type/Data/RowList.purs @@ -3,5 +3,6 @@ module Type.Data.RowList where import Prim.RowList (RowList) -- | A proxy to carry information about a rowlist. -data RLProxy (rowlist :: RowList Type) - = RLProxy +-- | **Deprecated as of v0.14.0 PureScript release**: use `Type.Proxy` instead. +data RLProxy :: RowList Type -> Type +data RLProxy rowlist = RLProxy diff --git a/src/Type/Proxy.purs b/src/Type/Proxy.purs new file mode 100644 index 00000000..879316fa --- /dev/null +++ b/src/Type/Proxy.purs @@ -0,0 +1,62 @@ +-- | The `Proxy` type and values are for situations where type information is +-- | required for an input to determine the type of an output, but where it is +-- | not possible or convenient to provide a _value_ for the input. +-- | +-- | A hypothetical example: if you have a class that is used to handle the +-- | result of an AJAX request, you may want to use this information to set the +-- | expected content type of the request, so you might have a class something +-- | like this: +-- | +-- | ``` purescript +-- | class AjaxResponse a where +-- | responseType :: a -> ResponseType +-- | fromResponse :: Foreign -> a +-- | ``` +-- | +-- | The problem here is `responseType` requires a value of type `a`, but we +-- | won't have a value of that type until the request has been completed. The +-- | solution is to use a `Proxy` type instead: +-- | +-- | ``` purescript +-- | class AjaxResponse a where +-- | responseType :: Proxy a -> ResponseType +-- | fromResponse :: Foreign -> a +-- | ``` +-- | +-- | We can now call `responseType (Proxy :: Proxy SomeContentType)` to produce +-- | a `ResponseType` for `SomeContentType` without having to construct some +-- | empty version of `SomeContentType` first. In situations like this where +-- | the `Proxy` type can be statically determined, it is recommended to pull +-- | out the definition to the top level and make a declaration like: +-- | +-- | ``` purescript +-- | _SomeContentType :: Proxy SomeContentType +-- | _SomeContentType = Proxy +-- | ``` +-- | +-- | That way the proxy value can be used as `responseType _SomeContentType` +-- | for improved readability. However, this is not always possible, sometimes +-- | the type required will be determined by a type variable. As PureScript has +-- | scoped type variables, we can do things like this: +-- | +-- | ``` purescript +-- | makeRequest :: URL -> ResponseType -> Aff _ Foreign +-- | makeRequest = ... +-- | +-- | fetchData :: forall a. (AjaxResponse a) => URL -> Aff _ a +-- | fetchData url = fromResponse <$> makeRequest url (responseType (Proxy :: Proxy a)) +-- | ``` +module Type.Proxy where + +-- | Proxy type for all `kind`s. +data Proxy :: forall k. k -> Type +data Proxy a = Proxy + +-- | Value proxy for kind `Type -> Type` types. +-- | **Deprecated as of v0.14.0 PureScript release**: use `Proxy` instead. +data Proxy2 :: (Type -> Type) -> Type +data Proxy2 f = Proxy2 + +-- | Value proxy for kind `Type -> Type -> Type` types. +-- | **Deprecated as of v0.14.0 PureScript release**: use `Proxy` instead. +data Proxy3 (a :: Type -> Type -> Type) = Proxy3