From 05b308f295722d4599d495ddb7d8accff01ce30e Mon Sep 17 00:00:00 2001 From: Tomasz Rybarczyk Date: Wed, 27 Nov 2019 00:27:50 +0100 Subject: [PATCH] Add base `Literal` type. Fix exports and type names. Add `IntLit`. --- spago.dhall | 1 + src/Literals.purs | 14 +++++++++++ src/Literals/Boolean.purs | 14 +++++++---- src/Literals/Int.purs | 53 +++++++++++++++++++++++++++++++++++++++ src/Literals/Literal.purs | 8 ++++++ src/Literals/Number.purs | 40 +++++++++++++---------------- src/Literals/String.purs | 14 +++++------ test/Main.purs | 24 ++++++------------ 8 files changed, 117 insertions(+), 51 deletions(-) create mode 100644 src/Literals.purs create mode 100644 src/Literals/Int.purs create mode 100644 src/Literals/Literal.purs diff --git a/spago.dhall b/spago.dhall index a51e75c..ecfb0cd 100644 --- a/spago.dhall +++ b/spago.dhall @@ -8,6 +8,7 @@ You can edit this file as you like. [ "assert" , "effect" , "console" + , "integers" , "numbers" , "partial" , "psci-support" diff --git a/src/Literals.purs b/src/Literals.purs new file mode 100644 index 0000000..2046c64 --- /dev/null +++ b/src/Literals.purs @@ -0,0 +1,14 @@ +module Literals + ( module Boolean + , module Int + , module Literal + , module Number + , module String + ) where + +import Literals.Boolean (BooleanLit, false_, true_) as Boolean +import Literals.Int (class Digit, class Int, class Int', IntLit, intLit) as Int +import Literals.Literal (Literal, toValue) as Literal +import Literals.Number (class Number, class Number', NumberLit, numberLit) as Number +import Literals.String (StringLit, stringLit) as String + diff --git a/src/Literals/Boolean.purs b/src/Literals/Boolean.purs index baffe1d..ac625c0 100644 --- a/src/Literals/Boolean.purs +++ b/src/Literals/Boolean.purs @@ -1,13 +1,17 @@ -module Literals.Boolean where +module Literals.Boolean + ( BooleanLit + , false_ + , true_ + ) where +import Literals.Literal (Literal) import Unsafe.Coerce (unsafeCoerce) -data True -data False +type BooleanLit sym = Literal Boolean sym -true_ :: True +true_ :: BooleanLit "true" true_ = unsafeCoerce true -false_ :: False +false_ :: BooleanLit "false" false_ = unsafeCoerce false diff --git a/src/Literals/Int.purs b/src/Literals/Int.purs new file mode 100644 index 0000000..6363ba1 --- /dev/null +++ b/src/Literals/Int.purs @@ -0,0 +1,53 @@ +module Literals.Int + ( IntLit + , IntegerPart + , Sign + , class Digit + , class Int + , class Int' + , intLit + , kind IntPart + ) where + +import Prelude + +import Data.Int (fromString) +import Data.Maybe (fromJust) +import Data.Symbol (class IsSymbol) +import Literals.Literal (Literal) +import Partial.Unsafe (unsafePartial) +import Prim.Symbol (class Cons) +import Type.Prelude (SProxy(..), reflectSymbol) +import Unsafe.Coerce (unsafeCoerce) + +class Digit (s :: Symbol) + +instance digit0 :: Digit "0" +else instance digit1 :: Digit "1" +else instance digit2 :: Digit "2" +else instance digit3 :: Digit "3" +else instance digit4 :: Digit "4" +else instance digit5 :: Digit "5" +else instance digit6 :: Digit "6" +else instance digit7 :: Digit "7" +else instance digit8 :: Digit "8" +else instance digit9 :: Digit "9" + +foreign import kind IntPart +foreign import data Sign :: IntPart +foreign import data IntegerPart :: IntPart + +class Int (sym :: Symbol) +instance intInstance :: (Int' h t Sign, Cons h t s) => Int s + +class Int' (head :: Symbol) (tail :: Symbol) (part :: IntPart) + +instance signPart :: (Cons h' t' t, Int' h' t' IntegerPart) => Int' "-" t Sign +else instance signPartEmpty :: (Int' h t IntegerPart) => Int' h t Sign +else instance lastIntegerPart :: (Digit h) => Int' h "" IntegerPart +else instance digitIntegerPart :: (Digit h, Cons h' t' t, Int' h' t' IntegerPart) => Int' h t IntegerPart + +type IntLit sym = Literal Int sym + +intLit :: forall sym. IsSymbol sym => Int sym => IntLit sym +intLit = unsafeCoerce $ unsafePartial $ fromJust $ fromString $ reflectSymbol (SProxy :: SProxy sym) diff --git a/src/Literals/Literal.purs b/src/Literals/Literal.purs new file mode 100644 index 0000000..952805b --- /dev/null +++ b/src/Literals/Literal.purs @@ -0,0 +1,8 @@ +module Literals.Literal where + +import Unsafe.Coerce (unsafeCoerce) + +foreign import data Literal :: Type -> Symbol -> Type + +toValue :: ∀ s a. Literal a s -> a +toValue = unsafeCoerce diff --git a/src/Literals/Number.purs b/src/Literals/Number.purs index 6f0c740..a3dec3a 100644 --- a/src/Literals/Number.purs +++ b/src/Literals/Number.purs @@ -1,26 +1,26 @@ -module Literals.Number where +module Literals.Number + ( FractionalPart + , IntegerPart + , NumberLit + , Sign + , class Number + , class Number' + , kind NumberPart + , numberLit + ) where + +import Prelude import Data.Maybe (fromJust) import Data.Number (fromString) import Data.Symbol (class IsSymbol, SProxy(..)) +import Literals.Int (class Digit) +import Literals.Literal (Literal) import Partial.Unsafe (unsafePartial) import Prim.Symbol (class Cons) import Type.Prelude (reflectSymbol) import Unsafe.Coerce (unsafeCoerce) -class Digit (s :: Symbol) - -instance digit0 :: Digit "0" -else instance digit1 :: Digit "1" -else instance digit2 :: Digit "2" -else instance digit3 :: Digit "3" -else instance digit4 :: Digit "4" -else instance digit5 :: Digit "5" -else instance digit6 :: Digit "6" -else instance digit7 :: Digit "7" -else instance digit8 :: Digit "8" -else instance digit9 :: Digit "9" - class Number (sym :: Symbol) instance numberInstance :: (Number' h t Sign, Cons h t s) => Number s @@ -35,16 +35,12 @@ class Number' (head :: Symbol) (tail :: Symbol) (part :: NumberPart) instance signPart :: (Cons h' t' t, Number' h' t' IntegerPart) => Number' "-" t Sign else instance signPartEmpty :: (Number' h t IntegerPart) => Number' h t Sign else instance pointIntegerPart :: (Cons h' t' t, Number' h' t' FractionalPart) => Number' "." t IntegerPart -else instance lastIntegerPart :: (Digit h) => Number' h "" IntegerPart -else instance digitIntegerPart :: (Digit h, Cons h' t' t, Number' h' t' IntegerPart) => Number' h t IntegerPart else instance lastFractionalPart :: (Digit h) => Number' h "" FractionalPart +else instance digitIntegerPart :: (Digit h, Cons h' t' t, Number' h' t' IntegerPart) => Number' h t IntegerPart else instance digitFractionalPart :: (Digit h, Cons h' t' t, Number' h' t' FractionalPart) => Number' h t FractionalPart -foreign import data Literal :: Symbol -> Type +type NumberLit sym = Literal Number sym -literal :: forall s. IsSymbol s => Number s => Literal s -literal = (unsafeCoerce (unsafePartial (fromJust (fromString (reflectSymbol (SProxy :: SProxy s)))))) - -toNumber :: forall s. Literal s -> Number -toNumber = unsafeCoerce +numberLit :: forall sym. IsSymbol sym => Number sym => NumberLit sym +numberLit = unsafeCoerce $ unsafePartial $ fromJust $ fromString $ reflectSymbol (SProxy :: SProxy sym) diff --git a/src/Literals/String.purs b/src/Literals/String.purs index 6ea0509..352e9a8 100644 --- a/src/Literals/String.purs +++ b/src/Literals/String.purs @@ -1,17 +1,15 @@ module Literals.String - ( Literal - , literal - , toString + ( stringLit + , StringLit ) where import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Literals.Literal (Literal) import Unsafe.Coerce (unsafeCoerce) -foreign import data Literal :: Symbol -> Type +type StringLit sym = Literal String sym -literal :: forall sym. IsSymbol sym => Literal sym -literal = unsafeCoerce (reflectSymbol (SProxy :: SProxy sym)) +stringLit :: forall sym. IsSymbol sym => StringLit sym +stringLit = unsafeCoerce (reflectSymbol (SProxy :: SProxy sym)) -toString :: forall sym. Literal sym -> String -toString = unsafeCoerce diff --git a/test/Main.purs b/test/Main.purs index c74e043..4717736 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -3,8 +3,7 @@ module Test.Main where import Prelude import Effect (Effect) -import Literals.Number (Literal, literal) as Number -import Literals.String (Literal, literal) as String +import Literals (NumberLit, StringLit, IntLit, intLit, numberLit, stringLit) import Test.Assert (assertEqual) import Unsafe.Coerce (unsafeCoerce) @@ -12,28 +11,21 @@ import Unsafe.Coerce (unsafeCoerce) main :: Effect Unit main = do assertEqual - { actual: unsafeCoerce (String.literal :: String.Literal "foo") + { actual: unsafeCoerce (stringLit :: StringLit "foo") , expected: "foo" } assertEqual - { actual: unsafeCoerce (Number.literal :: Number.Literal "8") + { actual: unsafeCoerce (numberLit :: NumberLit "8.0") , expected: 8.0 } - assertEqual - { actual: unsafeCoerce (Number.literal :: Number.Literal "-8") + assertEqual { actual: unsafeCoerce (numberLit :: NumberLit "-8.0") , expected: -8.0 } assertEqual - { actual: unsafeCoerce (Number.literal :: Number.Literal "100.0") - , expected: 100.0 + { actual: unsafeCoerce (intLit :: IntLit "8") + , expected: 8 } - assertEqual - { actual: unsafeCoerce (Number.literal :: Number.Literal "-100.0") - , expected: -100.0 - } - assertEqual - { actual: unsafeCoerce (Number.literal :: Number.Literal "0.0") - , expected: 0.0 + assertEqual { actual: unsafeCoerce (intLit :: IntLit "-8") + , expected: -8 } -