Skip to content

Commit 3c5e9a7

Browse files
committed
new repository
0 parents  commit 3c5e9a7

16 files changed

+918
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
result
2+
result-*

ascii-superset/ascii-superset.cabal

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
cabal-version: 3.0
2+
3+
name: ascii-superset
4+
version: 1.0.1.14
5+
synopsis: Representing ASCII with refined supersets
6+
category: Data, Text
7+
8+
description:
9+
This package defines classes which describe what subset of a type
10+
is valid as ASCII, as well as a type constructor representing a
11+
value of a superset that is known to be valid ASCII.
12+
13+
It also defines the Lift class, which provides a polymorphic lift
14+
operation that can be used to convert characters and strings into
15+
types that support a larger set of characters.
16+
17+
license: Apache-2.0
18+
license-file: license.txt
19+
20+
author: Chris Martin
21+
maintainer: Chris Martin, Julie Moronuki
22+
23+
homepage: https://github.com/typeclasses/ascii-superset
24+
bug-reports: https://github.com/typeclasses/ascii-superset/issues
25+
26+
extra-doc-files: *.md
27+
28+
source-repository head
29+
type: git
30+
location: git://github.com/typeclasses/ascii-superset.git
31+
32+
common base
33+
default-language: Haskell2010
34+
ghc-options: -Wall
35+
36+
default-extensions:
37+
NoImplicitPrelude
38+
39+
build-depends:
40+
ascii-char ^>= 1.0
41+
, base ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17
42+
, text ^>= 1.2.4.1 || ^>= 2.0
43+
44+
library
45+
import: base
46+
ghc-options: -fno-warn-unused-imports
47+
hs-source-dirs: library
48+
49+
default-extensions:
50+
DeriveDataTypeable
51+
DeriveGeneric
52+
DerivingStrategies
53+
GeneralizedNewtypeDeriving
54+
StandaloneDeriving
55+
56+
build-depends:
57+
bytestring ^>= 0.10.12 || ^>= 0.11
58+
, hashable ^>= 1.3.5 || ^>= 1.4
59+
60+
exposed-modules:
61+
ASCII.Superset
62+
, ASCII.Isomorphism
63+
, ASCII.Refinement
64+
, ASCII.Lift
65+
66+
test-suite test-ascii-superset
67+
import: base
68+
type: exitcode-stdio-1.0
69+
hs-source-dirs: test
70+
main-is: Main.hs
71+
72+
default-extensions:
73+
OverloadedStrings
74+
QuasiQuotes
75+
TemplateHaskell
76+
77+
build-depends:
78+
ascii-superset
79+
, hedgehog ^>= 1.0.5 || ^>= 1.1 || ^>= 1.2

ascii-superset/changelog.md

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
### 1.0.1.14 (2022-12-30)
2+
3+
Metadata changes only
4+
5+
### 1.0.1.13 (2022-04-20)
6+
7+
Drop support for `base` 4.11 (GHC 8.4) and `base` 4.12 (GHC 8.6)
8+
9+
Modify documentation on the `Lift` class. Previously it indicated that the class
10+
was for converting ASCII into supersets of ASCII. The class's purpose is now
11+
restated as being a conversion from any character set to any other larger
12+
character set. The purpose is to indicate that the ASCII subset types defined in
13+
the `ascii-numbers` package may reasonably have `Lift` instances.
14+
15+
### 1.0.1.12 (2022-03-22)
16+
17+
Switch test-suite over to `hedgehog`
18+
19+
### 1.0.0.10 (2022-01-09)
20+
21+
Support GHC 9.2
22+
23+
### 1.0.1.8 (2021-11-13)
24+
25+
Support `hashable-1.4`
26+
27+
### 1.0.1.6 (2021-09-26)
28+
29+
Add a test suite
30+
31+
Raise `text` lower bound to `1.2.3`
32+
33+
### 1.0.1.4 (2021-02-10)
34+
35+
Support GHC 9.0
36+
37+
### 1.0.1.2 (2021-02-09)
38+
39+
Support `bytestring-0.11`
40+
41+
### 1.0.1.0 (2021-01-27)
42+
43+
New functions:
44+
45+
- `convertCharOrFail`
46+
- `convertStringMaybe`
47+
- `convertStringOrFail`
48+
- `convertCharMaybe`
49+
50+
### 1.0.0.4 (2021-01-25)
51+
52+
Add some comments
53+
54+
### 1.0.0.2 (2020-05-18)
55+
56+
Support GHC 8.10
57+
58+
### 1.0.0.0 (2020-05-05)
59+
60+
Initial release
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
module ASCII.Isomorphism ( CharIso (..), asChar, StringIso (..) ) where
2+
3+
import ASCII.Char (Char)
4+
import ASCII.Superset (CharSuperset (..), StringSuperset (..))
5+
import Data.Function (id, (.))
6+
import Data.List (map)
7+
8+
class CharSuperset char => CharIso char
9+
where
10+
toChar :: char -> Char
11+
12+
asChar :: CharIso char => (Char -> Char) -> char -> char
13+
asChar f = fromChar . f . toChar
14+
15+
class StringSuperset string => StringIso string
16+
where
17+
toCharList :: string -> [Char]
18+
mapChars :: (Char -> Char) -> string -> string
19+
20+
-- | 'Char' is trivially isomorphic to itself. (This instance is uninteresting.)
21+
instance CharIso Char
22+
where
23+
toChar = id
24+
25+
instance CharIso char => StringIso [char]
26+
where
27+
toCharList = map toChar
28+
mapChars f = map (asChar f)

ascii-superset/library/ASCII/Lift.hs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
2+
3+
module ASCII.Lift ( Lift (..) ) where
4+
5+
import ASCII.Char (Char)
6+
import ASCII.Refinement (ASCII)
7+
import ASCII.Superset (CharSuperset, StringSuperset)
8+
9+
import qualified ASCII.Refinement as R
10+
import qualified ASCII.Superset as S
11+
12+
import qualified Prelude
13+
14+
-- | Embedding of one character set within another
15+
--
16+
-- The @subset@ and @superset@ types may be characters or strings in ASCII, some subset of ASCII, or some superset of ASCII.
17+
--
18+
class Lift subset superset
19+
where
20+
21+
{- | Converts from a smaller to a larger type.
22+
23+
>>> lift CapitalLetterA :: Word8
24+
65
25+
26+
>>> lift [CapitalLetterH,SmallLetterI,ExclamationMark] :: Text
27+
"Hi!"
28+
29+
Due to the highly polymorphic nature of the 'lift' function, often it must used with an explicit type signature or type application to avoid any type ambiguity.
30+
31+
-}
32+
33+
lift :: subset -> superset
34+
35+
-- | A value from an ASCII superset that has been refined by the 'ASCII' type constructor may be lifted back into the superset by unwrapping it from the 'ASCII' type.
36+
37+
instance Lift (ASCII superset) superset where lift = R.lift
38+
39+
-- | An ASCII 'Char' may be 'lift'ed into any larger character set (a 'CharSuperset'); for example, 'lift' can convert an ASCII character into a value of the standard 'Prelude.Char' type in "Prelude".
40+
41+
instance CharSuperset superset => Lift Char superset where lift = S.fromChar
42+
43+
-- | An ASCII 'Char' list may be 'lift'ed into a string of any larger character set (a 'StringSuperset'); for example, 'lift' can convert a list of ASCII characters into a value of the standard 'Prelude.String' type in "Prelude".
44+
45+
instance StringSuperset superset => Lift [Char] superset where lift = S.fromCharList
+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
module ASCII.Refinement
2+
(
3+
{- * ASCII type constructor -} ASCII, lift, asciiUnsafe,
4+
{- * Character functions -} validateChar, fromChar, toChar, substituteChar, asChar,
5+
{- * String functions -} validateString, fromCharList, toCharList, substituteString, mapChars
6+
)
7+
where
8+
9+
import qualified ASCII.Char as ASCII
10+
import qualified ASCII.Isomorphism as I
11+
import qualified ASCII.Superset as S
12+
13+
import ASCII.Superset (CharSuperset, StringSuperset)
14+
import Data.Bool (Bool (..))
15+
import Data.Data (Data)
16+
import Data.Eq (Eq)
17+
import Data.Function (id, ($), (.))
18+
import Data.Hashable (Hashable)
19+
import Data.List (map)
20+
import Data.Maybe (Maybe (..))
21+
import Data.Monoid (Monoid)
22+
import Data.Ord (Ord, (>))
23+
import Data.Semigroup (Semigroup)
24+
import GHC.Generics (Generic)
25+
import Prelude (succ)
26+
import Text.Show (Show, showList, showParen, showString, showsPrec)
27+
28+
{- | This type constructor indicates that a value from some ASCII superset is valid ASCII. The type parameter is the ASCII superset, which should be a type with an instance of either 'CharSuperset' or 'StringSuperset'.
29+
30+
For example, whereas a 'Data.Text.Text' value may contain a combination of ASCII and non-ASCII characters, a value of type @'ASCII' 'Data.Text.Text'@ may contain only ASCII characters.
31+
32+
-}
33+
34+
newtype ASCII superset = ASCII_Unsafe { lift :: superset }
35+
36+
deriving stock instance Eq superset => Eq (ASCII superset)
37+
38+
deriving stock instance Ord superset => Ord (ASCII superset)
39+
40+
deriving newtype instance Hashable superset => Hashable (ASCII superset)
41+
42+
deriving newtype instance Semigroup superset => Semigroup (ASCII superset)
43+
44+
deriving newtype instance Monoid superset => Monoid (ASCII superset)
45+
46+
deriving stock instance Data superset => Data (ASCII superset)
47+
48+
deriving stock instance Generic (ASCII superset)
49+
50+
instance Show superset => Show (ASCII superset)
51+
where
52+
showsPrec d x = showParen (d > app_prec) $
53+
showString "asciiUnsafe " . showsPrec (succ app_prec) (lift x)
54+
where app_prec = 10
55+
56+
showList x = showString "asciiUnsafe " . showList (map lift x)
57+
58+
instance CharSuperset char => CharSuperset (ASCII char)
59+
where
60+
isAsciiChar _ = True
61+
fromChar = asciiUnsafe . S.fromChar
62+
toCharUnsafe = S.toCharUnsafe . lift
63+
64+
instance CharSuperset char => I.CharIso (ASCII char)
65+
where
66+
toChar = S.toCharUnsafe
67+
68+
instance StringSuperset string => StringSuperset (ASCII string)
69+
where
70+
isAsciiString _ = True
71+
fromCharList = asciiUnsafe . S.fromCharList
72+
toCharListUnsafe = S.toCharListUnsafe . lift
73+
toCharListSub = S.toCharListUnsafe . lift
74+
substituteString = id
75+
76+
instance StringSuperset string => I.StringIso (ASCII string)
77+
where
78+
toCharList = S.toCharListUnsafe
79+
mapChars = S.mapCharsUnsafe
80+
81+
asciiUnsafe :: superset -> ASCII superset
82+
asciiUnsafe = ASCII_Unsafe
83+
84+
{- |
85+
86+
>>> map validateChar [-1, 65, 97, 128] :: [Maybe (ASCII Int)]
87+
[Nothing,Just (asciiUnsafe 65),Just (asciiUnsafe 97),Nothing]
88+
89+
-}
90+
91+
validateChar :: CharSuperset superset => superset -> Maybe (ASCII superset)
92+
validateChar x = if S.isAsciiChar x then Just (asciiUnsafe x) else Nothing
93+
94+
substituteChar :: CharSuperset superset => superset -> ASCII superset
95+
substituteChar x = if S.isAsciiChar x then asciiUnsafe x else fromChar ASCII.Substitute
96+
97+
fromChar :: CharSuperset superset => ASCII.Char -> ASCII superset
98+
fromChar = asciiUnsafe . S.fromChar
99+
100+
toChar :: CharSuperset superset => ASCII superset -> ASCII.Char
101+
toChar = S.toCharUnsafe . lift
102+
103+
{- |
104+
105+
>>> fromCharList [CapitalLetterH,SmallLetterI,ExclamationMark] :: ASCII Text
106+
asciiUnsafe "Hi!"
107+
108+
-}
109+
110+
fromCharList :: StringSuperset superset => [ASCII.Char] -> ASCII superset
111+
fromCharList = asciiUnsafe . S.fromCharList
112+
113+
{- |
114+
115+
>>> toCharList (substituteString "Piñata" :: ASCII Text)
116+
[CapitalLetterP,SmallLetterI,Substitute,SmallLetterA,SmallLetterT,SmallLetterA]
117+
118+
-}
119+
120+
toCharList :: StringSuperset superset => ASCII superset -> [ASCII.Char]
121+
toCharList = S.toCharListUnsafe . lift
122+
123+
{- | Forces a string from a larger character set into ASCII by using the 'ASCII.Substitute' character in place of any non-ASCII characters.
124+
125+
>>> substituteString "Cristóbal" :: ASCII Text
126+
asciiUnsafe "Crist\SUBbal"
127+
128+
-}
129+
130+
substituteString :: StringSuperset superset => superset -> ASCII superset
131+
substituteString = asciiUnsafe . S.substituteString
132+
133+
{- |
134+
135+
>>> map validateString ["Hello", "Cristóbal"] :: [Maybe (ASCII Text)]
136+
[Just (asciiUnsafe "Hello"),Nothing]
137+
138+
>>> map validateString ["Hello", "Cristóbal"] :: [Maybe (ASCII String)]
139+
[Just (asciiUnsafe "Hello"),Nothing]
140+
141+
-}
142+
143+
validateString :: StringSuperset superset => superset -> Maybe (ASCII superset)
144+
validateString x = if S.isAsciiString x then Just (asciiUnsafe x) else Nothing
145+
146+
asChar :: CharSuperset superset => (ASCII.Char -> ASCII.Char) -> ASCII superset -> ASCII superset
147+
asChar f = asciiUnsafe . S.asCharUnsafe f . lift
148+
149+
mapChars :: StringSuperset superset => (ASCII.Char -> ASCII.Char) -> ASCII superset -> ASCII superset
150+
mapChars f = asciiUnsafe . S.mapCharsUnsafe f . lift

0 commit comments

Comments
 (0)