Safe Haskell | None |
---|---|
Language | Haskell2010 |
Synopsis
- data a :| b
- data a :- b
- (.|) :: Depth a ~ Depth b => Proxy a -> Proxy b -> Proxy (a :| b)
- (.-) :: Proxy a -> Proxy b -> Proxy (a :- b)
- type Number nt n = NumberWithOffset nt n 0
- data NumberWithOffset nt (n :: Nat) (o :: Nat)
- data PadTo nt (n :: Nat) a
- type family ToTreeH (a :: [k]) :: [*] where ...
- type family ToTree2 (as :: [k]) :: [*] where ...
- type family ToTree64 (as :: [k]) :: [*] where ...
- type family Len (a :: [Symbol]) :: Nat where ...
- type family ToTree (a :: [k]) :: * where ...
- type family Concat (a :: [k]) :: * where ...
- type family Intersperse (a :: k) (b :: [k]) :: [k] where ...
- type family LeftSide (a :: *) :: * where ...
- type family RightSide (a :: *) :: * where ...
- leftSide :: Proxy (a :| b) -> Proxy a
- rightSide :: Proxy (a :| b) -> Proxy b
- type PowerOfTwo n = IsPowerOfTwo n ~ True
- type family IsPowerOfTwo (a :: Nat) :: Bool where ...
- type family BitsInPowerOfTwo (a :: Nat) :: Nat where ...
- type family Find a as :: Bool where ...
- type family HasDups (a :: [Symbol]) :: Bool where ...
- type family NoDups (a :: [Symbol]) :: Constraint where ...
- type family Depth (a :: k) :: Nat where ...
- getDepth :: forall a. KnownNat (Depth a) => Proxy a -> Integer
- type family NTimes (n :: Nat) (p :: *) where ...
- five :: Proxy a -> Proxy ((((a :- a) :- a) :- a) :- a)
- four :: Proxy a -> Proxy (((a :- a) :- a) :- a)
- three :: Proxy a -> Proxy ((a :- a) :- a)
- two :: Proxy a -> Proxy (a :- a)
- padHex :: forall n a. Proxy a -> Proxy (PadTo Hex n a)
- padDec :: forall n a. Proxy a -> Proxy (PadTo Dec n a)
- hex4 :: Proxy (Number Hex 4)
- hex8 :: Proxy (Number Hex 8)
- hex16 :: Proxy (Number Hex 16)
- hex32 :: Proxy (Number Hex 32)
- hex :: Proxy (Number Hex n)
- dec4 :: Proxy (Number Dec 4)
- dec8 :: Proxy (Number Dec 8)
- dec16 :: Proxy (Number Dec 16)
- dec32 :: Proxy (Number Dec 32)
- dec :: Proxy (Number Dec n)
- class MemRender a where
- addBits :: Coding PutM () -> ExceptT String (State ([String], Coding PutM ())) ()
- symbolString :: KnownSymbol a => Proxy a -> String
- stringSymbol :: String -> String
- parsePhrase :: MemRender p => Proxy p -> String -> Maybe ByteString
- parseMemorable :: (Memorable a, MemRender p, MemLen a ~ Depth p) => Proxy p -> String -> Maybe a
- rerender :: (MemRender a, MemRender b, Depth a ~ Depth b) => Proxy a -> Proxy b -> String -> Maybe String
- class NumberRender n where
- data Dec
- data Hex
- class Memorable a where
- memBitSize :: forall a. KnownNat (MemLen a) => Proxy a -> Int
- testMemLen :: forall a. (KnownNat (MemLen a), Memorable a) => a -> Bool
- putUnaligned :: (MonadPut m, FiniteBits b) => b -> Coding m ()
- renderMemorable :: (MemRender p, Depth p ~ MemLen a, Memorable a) => Proxy p -> a -> String
- runRender :: Memorable a => a -> ByteString
- runParser :: Memorable a => ByteString -> a
- renderMemorableByteString :: MemRender a => Proxy a -> ByteString -> String
- renderRandom :: forall a. (MemRender a, KnownNat (Depth a)) => Proxy a -> IO String
- renderHashable32 :: (MemRender p, Depth p ~ 32, Hashable a) => Proxy p -> a -> String
- renderHashable16 :: (MemRender p, Depth p ~ 16, Hashable a) => Proxy p -> a -> String
- renderHashable8 :: (MemRender p, Depth p ~ 8, Hashable a) => Proxy p -> a -> String
Documentation
Choice between two sub patterns. It's not safe to use this directly.
Use .|
instead.
Also, if you are parsing back rendered phrases, you must make sure that
the selected word is enough to choose a side. That is, a
and b
must
have unique first words. This is NOT checked, as it causes a HUGE
compile-time performance hit. If we can make it performant it may be
checked one day.
Append two patterns together by doing the first, then the second. See
also .-
(.|) :: Depth a ~ Depth b => Proxy a -> Proxy b -> Proxy (a :| b) Source #
Proxy version of :|
. It also constraints the two subpatterns to
being the same depth. Use this to add an extra bit to the pattern depth,
where the bit chooses to proceed down either the left or right side.
>>>
:set -XTypeApplications
>>>
:set -XDataKinds
>>>
import Data.Word
>>>
let myPattern = padHex (Proxy @"foo" .| Proxy @"bar")
>>>
renderMemorable myPattern (0x00 :: Word8)
"bar-00">>>
renderMemorable myPattern (0xff :: Word8)
"foo-7f"
See also ToTree
WARNING: Each side of the split must be unique. See the warning about :|
.
(.-) :: Proxy a -> Proxy b -> Proxy (a :- b) Source #
Proxy version of :-
.
The new pattern depth is the sum of the two parts.
>>> import Data.Word
>>> import Data.Memorable.Theme.Words
>>> let myPattern = words8 .- words8
>>> renderMemorable myPattern (0xabcd :: Word16)
"ages-old"
type Number nt n = NumberWithOffset nt n 0 Source #
data NumberWithOffset nt (n :: Nat) (o :: Nat) Source #
Captures n
bits and convertes them to a string via the nt
("number type")
argument after adding the offset. See Dec
, Hex
.
Instances
(NumberRender nt, KnownNat a, KnownNat o) => MemRender (NumberWithOffset nt a o :: Type) Source # | |
data PadTo nt (n :: Nat) a Source #
Pad the a
argument out to length n
by taking the remaining bits
and converting them via nt
(see Dec
and Hex
). If padding is required,
it is separated by a dash.
type family ToTreeH (a :: [k]) :: [*] where ... Source #
ToTreeH '[] = '[] | |
ToTreeH (x1 ': (x2 ': (x3 ': (x4 ': (x5 ': (x6 ': (x7 ': (x8 ': (x9 ': (x10 ': (x11 ': (x12 ': (x13 ': (x14 ': (x15 ': (x16 ': (x17 ': (x18 ': (x19 ': (x20 ': (x21 ': (x22 ': (x23 ': (x24 ': (x25 ': (x26 ': (x27 ': (x28 ': (x29 ': (x30 ': (x31 ': (x32 ': (x33 ': (x34 ': (x35 ': (x36 ': (x37 ': (x38 ': (x39 ': (x40 ': (x41 ': (x42 ': (x43 ': (x44 ': (x45 ': (x46 ': (x47 ': (x48 ': (x49 ': (x50 ': (x51 ': (x52 ': (x53 ': (x54 ': (x55 ': (x56 ': (x57 ': (x58 ': (x59 ': (x60 ': (x61 ': (x62 ': (x63 ': (x64 ': xs)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) = ToTree64 (x1 ': (x2 ': (x3 ': (x4 ': (x5 ': (x6 ': (x7 ': (x8 ': (x9 ': (x10 ': (x11 ': (x12 ': (x13 ': (x14 ': (x15 ': (x16 ': (x17 ': (x18 ': (x19 ': (x20 ': (x21 ': (x22 ': (x23 ': (x24 ': (x25 ': (x26 ': (x27 ': (x28 ': (x29 ': (x30 ': (x31 ': (x32 ': (x33 ': (x34 ': (x35 ': (x36 ': (x37 ': (x38 ': (x39 ': (x40 ': (x41 ': (x42 ': (x43 ': (x44 ': (x45 ': (x46 ': (x47 ': (x48 ': (x49 ': (x50 ': (x51 ': (x52 ': (x53 ': (x54 ': (x55 ': (x56 ': (x57 ': (x58 ': (x59 ': (x60 ': (x61 ': (x62 ': (x63 ': (x64 ': xs)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) | |
ToTreeH as = ToTree2 as |
type family ToTree64 (as :: [k]) :: [*] where ... Source #
ToTree64 '[] = '[] | |
ToTree64 (x1 ': (x2 ': (x3 ': (x4 ': (x5 ': (x6 ': (x7 ': (x8 ': (x9 ': (x10 ': (x11 ': (x12 ': (x13 ': (x14 ': (x15 ': (x16 ': (x17 ': (x18 ': (x19 ': (x20 ': (x21 ': (x22 ': (x23 ': (x24 ': (x25 ': (x26 ': (x27 ': (x28 ': (x29 ': (x30 ': (x31 ': (x32 ': (x33 ': (x34 ': (x35 ': (x36 ': (x37 ': (x38 ': (x39 ': (x40 ': (x41 ': (x42 ': (x43 ': (x44 ': (x45 ': (x46 ': (x47 ': (x48 ': (x49 ': (x50 ': (x51 ': (x52 ': (x53 ': (x54 ': (x55 ': (x56 ': (x57 ': (x58 ': (x59 ': (x60 ': (x61 ': (x62 ': (x63 ': (x64 ': xs)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) = ((((((x1 :| x2) :| (x3 :| x4)) :| ((x5 :| x6) :| (x7 :| x8))) :| (((x9 :| x10) :| (x11 :| x12)) :| ((x13 :| x14) :| (x15 :| x16)))) :| ((((x17 :| x18) :| (x19 :| x20)) :| ((x21 :| x22) :| (x23 :| x24))) :| (((x25 :| x26) :| (x27 :| x28)) :| ((x29 :| x30) :| (x31 :| x32))))) :| (((((x33 :| x34) :| (x35 :| x36)) :| ((x37 :| x38) :| (x39 :| x40))) :| (((x41 :| x42) :| (x43 :| x44)) :| ((x45 :| x46) :| (x47 :| x48)))) :| ((((x49 :| x50) :| (x51 :| x52)) :| ((x53 :| x54) :| (x55 :| x56))) :| (((x57 :| x58) :| (x59 :| x60)) :| ((x61 :| x62) :| (x63 :| x64)))))) ': ToTree64 xs |
type family ToTree (a :: [k]) :: * where ... Source #
Convert a '[Symbol]
to a balanced tree of :|
. Each result has equal
probability of occurring. Length of the list must be a power of two. This
is very useful for converting long lists of words into a usable pattern.
>>>
:kind! ToTree '["a", "b", "c", "d"]
ToTree '["a", "b", "c", "d"] :: * = ("a" :| "b") :| ("c" :| "d")
type family Intersperse (a :: k) (b :: [k]) :: [k] where ... Source #
Intersperse a '[] = '[] | |
Intersperse a (b ': '[]) = b ': '[] | |
Intersperse a (b ': cs) = b ': (a ': Intersperse a cs) |
type family LeftSide (a :: *) :: * where ... Source #
Useful to prevent haddock from expanding the type.
type family RightSide (a :: *) :: * where ... Source #
Useful to prevent haddock from expanding the type.
leftSide :: Proxy (a :| b) -> Proxy a Source #
Shrink a branching pattern by discarding the right hand side.
rightSide :: Proxy (a :| b) -> Proxy b Source #
Shrink a branching pattern by discarding the left hand side.
type PowerOfTwo n = IsPowerOfTwo n ~ True Source #
type family IsPowerOfTwo (a :: Nat) :: Bool where ... Source #
IsPowerOfTwo 1 = True | |
IsPowerOfTwo 2 = True | |
IsPowerOfTwo 4 = True | |
IsPowerOfTwo 8 = True | |
IsPowerOfTwo 16 = True | |
IsPowerOfTwo 32 = True | |
IsPowerOfTwo 64 = True | |
IsPowerOfTwo 128 = True | |
IsPowerOfTwo 256 = True | |
IsPowerOfTwo 512 = True | |
IsPowerOfTwo 1024 = True | |
IsPowerOfTwo 2048 = True | |
IsPowerOfTwo 4096 = True | |
IsPowerOfTwo 8192 = True |
type family BitsInPowerOfTwo (a :: Nat) :: Nat where ... Source #
BitsInPowerOfTwo 1 = 0 | |
BitsInPowerOfTwo 2 = 1 | |
BitsInPowerOfTwo 4 = 2 | |
BitsInPowerOfTwo 8 = 3 | |
BitsInPowerOfTwo 16 = 4 | |
BitsInPowerOfTwo 32 = 5 | |
BitsInPowerOfTwo 64 = 6 | |
BitsInPowerOfTwo 128 = 7 | |
BitsInPowerOfTwo 256 = 8 | |
BitsInPowerOfTwo 512 = 9 | |
BitsInPowerOfTwo 1024 = 10 | |
BitsInPowerOfTwo 2048 = 11 | |
BitsInPowerOfTwo 4096 = 12 | |
BitsInPowerOfTwo 8192 = 13 |
type family Find a as :: Bool where ... Source #
Find a '[] = False | |
Find a (a ': as) = True | |
Find a (b ': (a ': as)) = True | |
Find a (c ': (b ': (a ': as))) = True | |
Find a (d ': (c ': (b ': (a ': as)))) = True | |
Find a (e ': (d ': (c ': (b ': (a ': as))))) = True | |
Find a (f ': (e ': (d ': (c ': (b ': (a ': as)))))) = True | |
Find a (g ': (f ': (e ': (d ': (c ': (b ': (a ': as))))))) = True | |
Find a (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as)))))))) = True | |
Find a (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as))))))))) = True | |
Find a (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as)))))))))) = True | |
Find a (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as))))))))))) = True | |
Find a (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as)))))))))))) = True | |
Find a (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as))))))))))))) = True | |
Find a (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as)))))))))))))) = True | |
Find a (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as))))))))))))))) = True | |
Find a (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as)))))))))))))))) = True | |
Find a (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as))))))))))))))))) = True | |
Find a (r ': (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as)))))))))))))))))) = True | |
Find a (s ': (r ': (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as))))))))))))))))))) = True | |
Find a (t ': (s ': (r ': (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as)))))))))))))))))))) = True | |
Find a (u ': (t ': (s ': (r ': (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as))))))))))))))))))))) = True | |
Find a (v ': (u ': (t ': (s ': (r ': (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as)))))))))))))))))))))) = True | |
Find a (w ': (v ': (u ': (t ': (s ': (r ': (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as))))))))))))))))))))))) = True | |
Find a (x ': (w ': (v ': (u ': (t ': (s ': (r ': (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as)))))))))))))))))))))))) = True | |
Find a (y ': (x ': (w ': (v ': (u ': (t ': (s ': (r ': (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as))))))))))))))))))))))))) = True | |
Find a (z ': (y ': (x ': (w ': (v ': (u ': (t ': (s ': (r ': (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (a ': as)))))))))))))))))))))))))) = True | |
Find a (z ': (y ': (x ': (w ': (v ': (u ': (t ': (s ': (r ': (q ': (p ': (o ': (n ': (m ': (l ': (k ': (j ': (i ': (h ': (g ': (f ': (e ': (d ': (c ': (b ': (aa ': as)))))))))))))))))))))))))) = Find a as | |
Find a (b ': as) = Find a as |
type family NoDups (a :: [Symbol]) :: Constraint where ... Source #
type family Depth (a :: k) :: Nat where ... Source #
Determines the number of bits that a pattern will consume.
getDepth :: forall a. KnownNat (Depth a) => Proxy a -> Integer Source #
Get the depth of a pattern as a value-level Integer
.
>>> :set -XTypeApplications -XDataKinds
>>> getDepth (Proxy "foo" .| Proxy
"bar")
1
five :: Proxy a -> Proxy ((((a :- a) :- a) :- a) :- a) Source #
Put five things next to each other.
Same as using .-
repeatedly
padHex :: forall n a. Proxy a -> Proxy (PadTo Hex n a) Source #
Pad this pattern out with hex digits. Useful when you want some human
readability, but also want full coverage of the data. See Hex
for details.
>>>
import Data.Word
>>>
import Data.Memorable.Theme.Fantasy
>>>
renderMemorable (padHex rpgWeapons) (0xdeadbeef01020304 :: Word64)
"sacred-club-of-ghoul-charming-eef01020304"
hex :: Proxy (Number Hex n) Source #
A single hex number consuming n
bits, which it will try and figure
out from context (with leading 0's).
dec :: Proxy (Number Dec n) Source #
A single decimal number consuming n
bits, which it will try and figure
out from context (no leading 0's)
class MemRender a where Source #
The class that implements the main rendering function.
render :: Proxy a -> Coding Get String Source #
parser :: Proxy a -> ExceptT String (State ([String], Coding PutM ())) () Source #
Instances
KnownSymbol a => MemRender (a :: Symbol) Source # | |
(NumberRender nt, KnownNat a, KnownNat o) => MemRender (NumberWithOffset nt a o :: Type) Source # | |
(MemRender a, MemRender b) => MemRender (a :- b :: Type) Source # | |
(MemRender a, MemRender b) => MemRender (a :| b :: Type) Source # | |
(MemRender a, Depth a <= n, NumberRender nt, KnownNat n, KnownNat (Depth a)) => MemRender (PadTo nt n a :: Type) Source # | |
symbolString :: KnownSymbol a => Proxy a -> String Source #
stringSymbol :: String -> String Source #
parsePhrase :: MemRender p => Proxy p -> String -> Maybe ByteString Source #
parseMemorable :: (Memorable a, MemRender p, MemLen a ~ Depth p) => Proxy p -> String -> Maybe a Source #
Turn a memorable string back into a Memorable
value.
rerender :: (MemRender a, MemRender b, Depth a ~ Depth b) => Proxy a -> Proxy b -> String -> Maybe String Source #
Convert a memorable string into a different memorable string.
Useful for things like taking an existing md5, and converting it into a memorable one.
>>>
:set -XTypeApplications -XDataKinds
>>>
import Data.Memorable.Theme.Words
>>>
rerender hex (padHex @128 $ four words10) "2d4fbe4d5db8748c931b85c551d03360"
Just "lurk-lash-atop-hole-b8748c931b85c551d03360"
class NumberRender n where Source #
Class for capturing how to render numbers.
renderNumber :: Proxy n -> Integer -> Integer -> String Source #
readNumber :: Proxy n -> Integer -> String -> Maybe Integer Source #
Instances
NumberRender Hex Source # | |
NumberRender Dec Source # | |
Render numbers as decimal numbers. Does not pad.
Render numbers as hexadecimal numbers. Pads with 0s.
class Memorable a where Source #
Class for all things that can be converted to memorable strings.
See renderMemorable
for how to use.
Instances
testMemLen :: forall a. (KnownNat (MemLen a), Memorable a) => a -> Bool Source #
Use this with tasty-quickcheck (or your prefered testing framework) to
make sure you aren't lying about MemLen
.
testProperty "MemLen Word8" $ forAll (arbitrary :: Gen Word8) testMemLen
putUnaligned :: (MonadPut m, FiniteBits b) => b -> Coding m () Source #
renderMemorable :: (MemRender p, Depth p ~ MemLen a, Memorable a) => Proxy p -> a -> String Source #
This is the function to use when you want to turn your values into a memorable strings.
>>>
import Data.Word
>>>
import Data.Memorable.Theme.Words
>>>
let myPattern = words8 .- words8
>>>
renderMemorable myPattern (0x0123 :: Word16)
"cats-bulk"
runRender :: Memorable a => a -> ByteString Source #
runParser :: Memorable a => ByteString -> a Source #
renderMemorableByteString :: MemRender a => Proxy a -> ByteString -> String Source #
Render a ByteString
as a more memorable String
.
renderRandom :: forall a. (MemRender a, KnownNat (Depth a)) => Proxy a -> IO String Source #
Generate a random string.
renderHashable32 :: (MemRender p, Depth p ~ 32, Hashable a) => Proxy p -> a -> String Source #
Render any Hashable
value as a 32 bit pattern.