module Text.Seonbi.Hangul
( JamoTriple
, fromJamoTriple
, isHangulSyllable
, toJamoTriple
) where
type JamoTriple = (Char, Char, Maybe Char)
isHangulSyllable :: Char -> Bool
isHangulSyllable :: Char -> Bool
isHangulSyllable Char
c =
Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\xac00' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xd7a3';
syllableBase :: Int
syllableBase :: Int
syllableBase = Int
0xac00
initialBase :: Int
initialBase :: Int
initialBase = Int
0x1100
vowelBase :: Int
vowelBase :: Int
vowelBase = Int
0x1161
finalBase :: Int
finalBase :: Int
finalBase = Int
0x11a7
vowelCount :: Int
vowelCount :: Int
vowelCount = Int
21;
finalCount :: Int
finalCount :: Int
finalCount = Int
28;
toJamoTriple :: Char -> Maybe JamoTriple
toJamoTriple :: Char -> Maybe JamoTriple
toJamoTriple Char
c
| Char -> Bool
isHangulSyllable Char
c = JamoTriple -> Maybe JamoTriple
forall a. a -> Maybe a
Just
( Int -> Char
forall a. Enum a => Int -> a
toEnum (Int -> Char) -> Int -> Char
forall a b. (a -> b) -> a -> b
$ Int
initialBase Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ((Int
syllable Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
finalCount) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
vowelCount)
, Int -> Char
forall a. Enum a => Int -> a
toEnum (Int -> Char) -> Int -> Char
forall a b. (a -> b) -> a -> b
$ Int
vowelBase Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ((Int
syllable Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
finalCount) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
vowelCount)
, case Int
syllable Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
finalCount of
Int
0 -> Maybe Char
forall a. Maybe a
Nothing
Int
f -> Char -> Maybe Char
forall a. a -> Maybe a
Just (Char -> Maybe Char) -> Char -> Maybe Char
forall a b. (a -> b) -> a -> b
$ Int -> Char
forall a. Enum a => Int -> a
toEnum (Int
finalBase Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
f)
)
| Bool
otherwise = Maybe JamoTriple
forall a. Maybe a
Nothing
where
syllable :: Int
syllable :: Int
syllable = Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
c Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
syllableBase
fromJamoTriple :: JamoTriple -> Maybe Char
fromJamoTriple :: JamoTriple -> Maybe Char
fromJamoTriple (Char
initial, Char
vowel, Maybe Char
final)
| Int
initialIndex Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Maybe Char
forall a. Maybe a
Nothing
| Int
initialIndex Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
18 = Maybe Char
forall a. Maybe a
Nothing
| Int
vowelIndex Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Maybe Char
forall a. Maybe a
Nothing
| Int
vowelIndex Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
20 = Maybe Char
forall a. Maybe a
Nothing
| Int
finalIndex Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = Maybe Char
forall a. Maybe a
Nothing
| Int
finalIndex Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
27 = Maybe Char
forall a. Maybe a
Nothing
| Bool
otherwise = Char -> Maybe Char
forall a. a -> Maybe a
Just (Char -> Maybe Char) -> Char -> Maybe Char
forall a b. (a -> b) -> a -> b
$ Int -> Char
forall a. Enum a => Int -> a
toEnum (Int -> Char) -> Int -> Char
forall a b. (a -> b) -> a -> b
$ Int
syllableBase Int -> Int -> Int
forall a. Num a => a -> a -> a
+
(Int
initialIndex Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
vowelCount Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
vowelIndex) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
finalCount Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
finalIndex
where
initialIndex :: Int
initialIndex :: Int
initialIndex = Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
initial Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
initialBase
vowelIndex :: Int
vowelIndex :: Int
vowelIndex = Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
vowel Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
vowelBase
finalIndex :: Int
finalIndex :: Int
finalIndex = Int -> (Char -> Int) -> Maybe Char -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 (\ Char
f -> Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
f Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
finalBase) Maybe Char
final