git.iko.soy/purescript-literals
on main help sign in
16 files changed+304−38
since splitsnapshots
unifiedsplit
LICENSE+21 bower.json+27 packages.dhall+2−3 spago.dhall+15−16 src/Literal.purs−16 src/Literals.purs+13 src/Literals/Boolean.purs+17 src/Literals/Int.purs+54 src/Literals/Literal.purs+15 src/Literals/Null.js+1 src/Literals/Null.purs+17 src/Literals/Number.purs+45 src/Literals/String.purs+14 src/Literals/Undefined.js+1 src/Literals/Undefined.purs+19 test/Main.purs+43−3
LICENSEnew file+21
@@ -0,0 +1,21 @@
1+MIT License
2+
3+Copyright (c) 2020 Jan Vincent Liwanag
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy
6+of this software and associated documentation files (the "Software"), to deal
7+in the Software without restriction, including without limitation the rights
8+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+copies of the Software, and to permit persons to whom the Software is
10+furnished to do so, subject to the following conditions:
11+
12+The above copyright notice and this permission notice shall be included in all
13+copies or substantial portions of the Software.
14+
15+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+SOFTWARE.
bower.jsonnew file+27
@@ -0,0 +1,27 @@
1+{
2+ "name": "purescript-literals",
3+ "license": [
4+ "MIT"
5+ ],
6+ "repository": {
7+ "type": "git",
8+ "url": "https://github.com/rowtype-yoga/purescript-literals.git"
9+ },
10+ "ignore": [
11+ "**/.*",
12+ "node_modules",
13+ "bower_components",
14+ "output"
15+ ],
16+ "dependencies": {
17+ "purescript-assert": "^v6.0.0",
18+ "purescript-effect": "^v4.0.0",
19+ "purescript-integers": "^v6.0.0",
20+ "purescript-maybe": "^v6.0.0",
21+ "purescript-numbers": "^v9.0.0",
22+ "purescript-partial": "^v4.0.0",
23+ "purescript-prelude": "^v6.0.0",
24+ "purescript-typelevel-prelude": "^v7.0.0",
25+ "purescript-unsafe-coerce": "^v6.0.0"
26+ }
27+}
packages.dhall+2−3
@@ -116,10 +116,9 @@ let additions =
116116 }
117117-------------------------------
118118-}
119−
120−
121119let upstream =
122− https://github.com/purescript/package-sets/releases/download/psc-0.13.4-20191110/packages.dhall sha256:563a7f694e18e6399f7f6d01f5b7e3c3345781655d99945768f48e458feb93a4
120+ https://github.com/purescript/package-sets/releases/download/psc-0.15.2-20220530/packages.dhall
121+ sha256:15dd8041480502850e4043ea2977ed22d6ab3fc24d565211acde6f8c5152a799
123122
124123let overrides = {=}
125124
spago.dhall+15−16
@@ -1,18 +1,17 @@
1−{-
2−Welcome to a Spago project!
3−You can edit this file as you like.
4−-}
5−{ name =
6− "literal"
1+{ name = "literals"
2+, license = "MIT"
3+, repository = "https://github.com/rowtype-yoga/purescript-literals.git"
74, dependencies =
8− [ "assert"
9− , "effect"
10− , "console"
11− , "psci-support"
12− , "unsafe-coerce"
13− ]
14−, packages =
15− ./packages.dhall
16−, sources =
17− [ "src/**/*.purs", "test/**/*.purs" ]
5+ [ "assert"
6+ , "effect"
7+ , "integers"
8+ , "maybe"
9+ , "numbers"
10+ , "partial"
11+ , "prelude"
12+ , "typelevel-prelude"
13+ , "unsafe-coerce"
14+ ]
15+, packages = ./packages.dhall
16+, sources = [ "src/**/*.purs", "test/**/*.purs" ]
1817}
src/Literal.pursdeleted−16
@@ -1,16 +0,0 @@
1−module Literal
2− ( Literal
3− , literal
4− , toString
5− ) where
6−
7−import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol)
8−import Unsafe.Coerce (unsafeCoerce)
9−
10−foreign import data Literal :: Symbol -> Type
11−
12−literal :: forall sym. IsSymbol sym => Literal sym
13−literal = unsafeCoerce (reflectSymbol (SProxy :: SProxy sym))
14−
15−toString :: forall sym. Literal sym -> String
16−toString = unsafeCoerce
src/Literals.pursnew file+13
@@ -0,0 +1,13 @@
1+module Literals
2+ ( module Boolean
3+ , module Int
4+ , module Literal
5+ , module Number
6+ , module String
7+ ) where
8+
9+import Literals.Boolean (BooleanLit, false_, true_) as Boolean
10+import Literals.Int (class Digit, class Int, class Int', IntLit, intLit) as Int
11+import Literals.Literal (Literal, toValue) as Literal
12+import Literals.Number (class Number, class Number', NumberLit, numberLit) as Number
13+import Literals.String (StringLit, stringLit) as String
src/Literals/Boolean.pursnew file+17
@@ -0,0 +1,17 @@
1+module Literals.Boolean
2+ ( BooleanLit
3+ , false_
4+ , true_
5+ ) where
6+
7+import Literals.Literal (Literal)
8+import Unsafe.Coerce (unsafeCoerce)
9+
10+type BooleanLit sym = Literal Boolean sym
11+
12+true_ :: BooleanLit "true"
13+true_ = unsafeCoerce true
14+
15+false_ :: BooleanLit "false"
16+false_ = unsafeCoerce false
17+
src/Literals/Int.pursnew file+54
@@ -0,0 +1,54 @@
1+module Literals.Int
2+ ( IntLit
3+ , IntegerPart
4+ , Sign
5+ , class Digit
6+ , class Int
7+ , class Int'
8+ , intLit
9+ , IntPart
10+ ) where
11+
12+import Prelude
13+
14+import Data.Int (fromString)
15+import Data.Maybe (fromJust)
16+import Data.Symbol (class IsSymbol)
17+import Literals.Literal (Literal)
18+import Partial.Unsafe (unsafePartial)
19+import Prim.Symbol (class Cons)
20+import Type.Prelude (reflectSymbol)
21+import Type.Proxy (Proxy(..))
22+import Unsafe.Coerce (unsafeCoerce)
23+
24+class Digit (s :: Symbol)
25+
26+instance digit0 :: Digit "0"
27+else instance digit1 :: Digit "1"
28+else instance digit2 :: Digit "2"
29+else instance digit3 :: Digit "3"
30+else instance digit4 :: Digit "4"
31+else instance digit5 :: Digit "5"
32+else instance digit6 :: Digit "6"
33+else instance digit7 :: Digit "7"
34+else instance digit8 :: Digit "8"
35+else instance digit9 :: Digit "9"
36+
37+data IntPart
38+foreign import data Sign :: IntPart
39+foreign import data IntegerPart :: IntPart
40+
41+class Int (sym :: Symbol)
42+instance intInstance :: (Int' h t Sign, Cons h t s) => Int s
43+
44+class Int' (head :: Symbol) (tail :: Symbol) (part :: IntPart)
45+
46+instance signPart :: (Cons h' t' t, Int' h' t' IntegerPart) => Int' "-" t Sign
47+else instance signPartEmpty :: (Int' h t IntegerPart) => Int' h t Sign
48+else instance lastIntegerPart :: (Digit h) => Int' h "" IntegerPart
49+else instance digitIntegerPart :: (Digit h, Cons h' t' t, Int' h' t' IntegerPart) => Int' h t IntegerPart
50+
51+type IntLit sym = Literal Int sym
52+
53+intLit :: forall sym. IsSymbol sym => Int sym => IntLit sym
54+intLit = unsafeCoerce $ unsafePartial $ fromJust $ fromString $ reflectSymbol (Proxy :: Proxy sym)
src/Literals/Literal.pursnew file+15
@@ -0,0 +1,15 @@
1+module Literals.Literal where
2+
3+import Prelude
4+
5+import Unsafe.Coerce (unsafeCoerce)
6+
7+foreign import data Literal :: Type -> Symbol -> Type
8+
9+instance literalEq :: Eq (Literal typ sym) where
10+ eq _ _ = true
11+instance literalShow :: Show typ => Show (Literal typ sym) where
12+ show a = "(Literal " <> (show $ toValue a) <> ")"
13+
14+toValue :: ∀ s a. Literal a s -> a
15+toValue = unsafeCoerce
src/Literals/Null.jsnew file+1
@@ -0,0 +1 @@
1+export _null = null;
src/Literals/Null.pursnew file+17
@@ -0,0 +1,17 @@
1+module Literals.Null
2+ ( Null
3+ , null
4+ )
5+where
6+
7+import Prelude
8+
9+foreign import data Null :: Type
10+
11+foreign import _null :: Null
12+
13+null :: Null
14+null = _null
15+
16+instance showNull :: Show Null where
17+ show _ = "null"
src/Literals/Number.pursnew file+45
@@ -0,0 +1,45 @@
1+module Literals.Number
2+ ( FractionalPart
3+ , IntegerPart
4+ , NumberLit
5+ , Sign
6+ , class Number
7+ , class Number'
8+ , NumberPart
9+ , numberLit
10+ ) where
11+
12+import Prelude
13+
14+import Data.Maybe (fromJust)
15+import Data.Number (fromString)
16+import Data.Symbol (class IsSymbol)
17+import Literals.Int (class Digit)
18+import Literals.Literal (Literal)
19+import Partial.Unsafe (unsafePartial)
20+import Prim.Symbol (class Cons)
21+import Type.Prelude (reflectSymbol, Proxy(..))
22+import Unsafe.Coerce (unsafeCoerce)
23+
24+class Number (sym :: Symbol)
25+
26+instance numberInstance :: (Number' h t Sign, Cons h t s) => Number s
27+
28+data NumberPart
29+foreign import data Sign :: NumberPart
30+foreign import data IntegerPart :: NumberPart
31+foreign import data FractionalPart :: NumberPart
32+
33+class Number' (head :: Symbol) (tail :: Symbol) (part :: NumberPart)
34+
35+instance signPart :: (Cons h' t' t, Number' h' t' IntegerPart) => Number' "-" t Sign
36+else instance signPartEmpty :: (Number' h t IntegerPart) => Number' h t Sign
37+else instance pointIntegerPart :: (Cons h' t' t, Number' h' t' FractionalPart) => Number' "." t IntegerPart
38+else instance lastFractionalPart :: (Digit h) => Number' h "" FractionalPart
39+else instance digitIntegerPart :: (Digit h, Cons h' t' t, Number' h' t' IntegerPart) => Number' h t IntegerPart
40+else instance digitFractionalPart :: (Digit h, Cons h' t' t, Number' h' t' FractionalPart) => Number' h t FractionalPart
41+
42+type NumberLit sym = Literal Number sym
43+
44+numberLit :: forall sym. IsSymbol sym => Number sym => NumberLit sym
45+numberLit = unsafeCoerce $ unsafePartial $ fromJust $ fromString $ reflectSymbol (Proxy :: Proxy sym)
src/Literals/String.pursnew file+14
@@ -0,0 +1,14 @@
1+module Literals.String
2+ ( stringLit
3+ , StringLit
4+ ) where
5+
6+import Data.Symbol (class IsSymbol, reflectSymbol)
7+import Type.Proxy (Proxy(..))
8+import Literals.Literal (Literal)
9+import Unsafe.Coerce (unsafeCoerce)
10+
11+type StringLit sym = Literal String sym
12+
13+stringLit :: forall sym. IsSymbol sym => StringLit sym
14+stringLit = unsafeCoerce (reflectSymbol (Proxy :: Proxy sym))
src/Literals/Undefined.jsnew file+1
@@ -0,0 +1 @@
1+export const _undefined = undefined;
src/Literals/Undefined.pursnew file+19
@@ -0,0 +1,19 @@
1+module Literals.Undefined
2+ ( Undefined
3+ , undefined
4+ )
5+where
6+
7+import Prelude
8+
9+foreign import data Undefined :: Type
10+
11+foreign import _undefined :: Undefined
12+
13+undefined :: Undefined
14+undefined = _undefined
15+
16+instance undefinedEq :: Eq Undefined where
17+ eq _ _ = true
18+instance undefinedShow :: Show Undefined where
19+ show _ = "Undefined"
test/Main.purs+43−3
@@ -3,13 +3,53 @@ module Test.Main where
33import Prelude
44
55import Effect (Effect)
6−import Literal (Literal, literal)
7−import Test.Assert (assertEqual)
6+import Literals (NumberLit, StringLit, IntLit, intLit, numberLit, stringLit)
7+import Literals.Undefined (undefined)
8+import Test.Assert (assertEqual, assertTrue)
89import Unsafe.Coerce (unsafeCoerce)
910
11+
1012main :: Effect Unit
1113main = do
1214 assertEqual
13− { actual: unsafeCoerce (literal :: Literal "foo")
15+ { actual: unsafeCoerce (stringLit :: StringLit "foo")
1416 , expected: "foo"
1517 }
18+ assertEqual
19+ { actual: unsafeCoerce (numberLit :: NumberLit "8.0")
20+ , expected: 8.0
21+ }
22+ assertEqual
23+ { actual: unsafeCoerce (numberLit :: NumberLit "-8.0")
24+ , expected: -8.0
25+ }
26+ assertEqual
27+ { actual: unsafeCoerce (intLit :: IntLit "8")
28+ , expected: 8
29+ }
30+ assertEqual
31+ { actual: unsafeCoerce (intLit :: IntLit "-8")
32+ , expected: -8
33+ }
34+
35+ -- Eq instance
36+ assertTrue $ undefined == undefined
37+ assertTrue $ (stringLit :: StringLit "foo") == (stringLit :: StringLit "foo")
38+
39+ -- Show instance
40+ assertEqual
41+ { actual: show (stringLit :: StringLit "foo")
42+ , expected: "(Literal \"foo\")"
43+ }
44+ assertEqual
45+ { actual: show (numberLit :: NumberLit "8.0")
46+ , expected: "(Literal 8.0)"
47+ }
48+ assertEqual
49+ { actual: show (intLit :: IntLit "8")
50+ , expected: "(Literal 8)"
51+ }
52+ assertEqual
53+ { actual: show undefined
54+ , expected: "Undefined"
55+ }