{-# OPTIONS_HADDOCK show-extensions #-}
{-# LANGUAGE ScopedTypeVariables #-}


-- |
-- Module      :  Interpreter.StringConversion
-- Copyright   :  (c) OleksandrZhabenko 2021-2022
-- License     :  MIT
-- Stability   :  Experimental
-- Maintainer  :  olexandr543@yahoo.com
--
-- A library that has commonly used function for the phonetic-languages implementations.

module Interpreter.StringConversion where

import Text.Read (readMaybe)
import Data.Maybe (fromJust,fromMaybe)
import Data.Char (isDigit)
import Data.List (sort,(\\))
import Data.Monoid (mappend)
import Control.Exception

{-| Converts the second given string into the form that can be easily used by the phonetic-languages-simplified-* implementations. -}
convStringInterpreter :: String -> String -> String
convStringInterpreter :: String -> String -> String
convStringInterpreter String
contrs String
xs
 | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
contrs = String
xs
 | [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> (String -> [String]) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Bool) -> String -> Bool
forall a b. (a -> b) -> a -> b
$ String
xs = String
xs
 | case (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
y -> Char -> Bool
isDigit Char
y Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'/' Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-') String
contrs of { Char
a:Char
'/':String
bs -> Char
a Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'/' Bool -> Bool -> Bool
&& Char
a Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'0' ; ~String
rrr -> Bool
False } =
     let ys :: String
ys = (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
y -> Char -> Bool
isDigit Char
y Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'/' Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-') String
contrs in
       case String
ys of
         ~Char
a:Char
'/':String
bs -> let wordsN :: [String]
wordsN = String -> [String]
words String
xs
                          wordN :: Int
wordN = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
1 (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe [Char
a]::Maybe Int)) ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
wordsN)
                          pos :: Int
pos = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe String
bs::Maybe Int)
                          wrdP :: String
wrdP = [String]
wordsN [String] -> Int -> String
forall a. [a] -> Int -> a
!! (Int
wordN Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
                          (String
ts,String
us) | Int
pos Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
pos String
wrdP
                                  | Bool
otherwise = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
wrdP Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
pos) String
wrdP
                          twoWords :: String
twoWords = String
ts String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:String
us)
                          ([String]
wss,[String]
tss) = Int -> [String] -> ([String], [String])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
wordN Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [String]
wordsN
                          kss :: [String]
kss = Int -> [String] -> [String]
forall a. Int -> [a] -> [a]
drop Int
1 [String]
tss in
                            if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
wss then String
twoWords String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:[String] -> String
unwords [String]
kss)
                            else [String] -> String
unwords [String]
wss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:String
twoWords) String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:[String] -> String
unwords [String]
kss)
 | String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ((Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
t -> if ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
10 then Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' else Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& [Char
t] String -> String -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> String
forall a. Show a => a -> String
show ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs)) (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
contrs) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 = String
xs
 -- The following case is changed since the version 0.6.0.0 to support concatenations of the arbitrary two words, not needed to be consequent ones.
 | Bool
otherwise = let cntrs :: String
cntrs = (if Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
1 ((Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter Char -> Bool
isDigit String
contrs) String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"0" then String
"0" else []) String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend`
                     ((Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
t -> if ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
10 then Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9'
                                    else Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& [Char
t] String -> String -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> String
forall a. Show a => a -> String
show ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs)) (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
contrs)
                   tss :: [String]
tss = String -> [String]
words String
xs in
                     case String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
cntrs of
                      Int
2 -> let pos :: Int
pos = Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe (Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
1 String
cntrs)::Maybe Int)
                               number :: Int
number = Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe (Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
1 String
cntrs)::Maybe Int)
                               ([String]
zss,[String]
yss) = Int -> [String] -> ([String], [String])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [String]
tss
                               ([String]
kss,[String]
lss) = Int -> [String] -> ([String], [String])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
number [String]
yss in
                                 if [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
tss Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
number Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 then String
xs
                                 else if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
zss then [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
kss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
unwords [String]
lss
                                      else [String] -> String
unwords [String]
zss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
kss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
unwords [String]
lss
                      Int
_ -> let idxs :: [Int]
idxs = (Char -> Int) -> String -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Char
x -> Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe [Char
x]::Maybe Int)) (String -> [Int]) -> String -> [Int]
forall a b. (a -> b) -> a -> b
$ (if Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
1 String
cntrs String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"0" then Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
1 String
cntrs else String
cntrs)
                               wordsN :: [String]
wordsN = (Int -> String) -> [Int] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
i -> [String]
tss [String] -> Int -> String
forall a. [a] -> Int -> a
!! (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)) [Int]
idxs
                               restWords :: [String]
restWords = [String]
tss [String] -> [String] -> [String]
forall a. Eq a => [a] -> [a] -> [a]
\\ [String]
wordsN
                                 in [String] -> String
unwords [String]
restWords String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
wordsN

{-| Variant of the 'convStringInterpreter' with the additional possibility to correct splitting after revision. -}
convStringInterpreterIO :: String -> String -> IO String
convStringInterpreterIO :: String -> String -> IO String
convStringInterpreterIO String
contrs String
xs
 | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
contrs = String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
xs
 | [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> (String -> [String]) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Bool) -> String -> Bool
forall a b. (a -> b) -> a -> b
$ String
xs = String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
xs
 | case (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
y -> Char -> Bool
isDigit Char
y Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'/' Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-') String
contrs of { Char
a:Char
'/':String
bs -> Char
a Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'/' Bool -> Bool -> Bool
&& Char
a Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'0' ; ~String
rrr -> Bool
False } =
     let ys :: String
ys = (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
y -> Char -> Bool
isDigit Char
y Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'/' Bool -> Bool -> Bool
|| Char
y Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-') String
contrs in
       case String
ys of
         ~Char
a:Char
'/':String
bs -> do
                        let wordsN :: [String]
wordsN = String -> [String]
words String
xs
                            wordN :: Int
wordN = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
1 (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe [Char
a]::Maybe Int)) ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
wordsN)
                            pos :: Int
pos = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe String
bs::Maybe Int)
                            wrdP :: String
wrdP = [String]
wordsN [String] -> Int -> String
forall a. [a] -> Int -> a
!! (Int
wordN Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
                        if Int -> Int
forall a. Num a => a -> a
abs Int
pos Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
8 then do
                          Int -> String -> IO Int
corr Int
pos String
wrdP IO Int -> (Int -> IO String) -> IO String
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Int
pos2 -> Int -> String -> Int -> [String] -> IO String
forall (m :: * -> *).
Monad m =>
Int -> String -> Int -> [String] -> m String
correctionF Int
pos2 String
wrdP Int
wordN [String]
wordsN
                        else Int -> String -> Int -> [String] -> IO String
forall (m :: * -> *).
Monad m =>
Int -> String -> Int -> [String] -> m String
correctionF Int
pos String
wrdP Int
wordN [String]
wordsN
 | String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ((Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
t -> if ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
10 then Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9' else Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& [Char
t] String -> String -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> String
forall a. Show a => a -> String
show ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs)) (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
contrs) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 = String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
xs
 | Bool
otherwise = let cntrs :: String
cntrs = (if Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
1 ((Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter Char -> Bool
isDigit String
contrs) String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"0" then String
"0" else []) String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend`
                     ((Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (\Char
t -> if ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
10 then Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9'
                                    else Char
t Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'1' Bool -> Bool -> Bool
&& [Char
t] String -> String -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> String
forall a. Show a => a -> String
show ([String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> (String -> [String]) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
xs)) (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
contrs)
                   tss :: [String]
tss = String -> [String]
words String
xs in
                     case String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
cntrs of
                      Int
2 -> let pos :: Int
pos = Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe (Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
1 String
cntrs)::Maybe Int)
                               number :: Int
number = Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe (Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
1 String
cntrs)::Maybe Int)
                               ([String]
zss,[String]
yss) = Int -> [String] -> ([String], [String])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [String]
tss
                               ([String]
kss,[String]
lss) = Int -> [String] -> ([String], [String])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
number [String]
yss in
                                 if [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
tss Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
number Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 then String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
xs
                                 else if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
zss then String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
kss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
unwords [String]
lss)
                                      else String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> String
unwords [String]
zss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
kss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
unwords [String]
lss)
                      Int
_ -> let idxs :: [Int]
idxs = (Char -> Int) -> String -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (\Char
x -> Maybe Int -> Int
forall a. HasCallStack => Maybe a -> a
fromJust (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe [Char
x]::Maybe Int)) (String -> [Int]) -> String -> [Int]
forall a b. (a -> b) -> a -> b
$ (if Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
1 String
cntrs String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"0" then Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
1 String
cntrs else String
cntrs)
                               wordsN :: [String]
wordsN = (Int -> String) -> [Int] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
i -> [String]
tss [String] -> Int -> String
forall a. [a] -> Int -> a
!! (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)) [Int]
idxs
                               restWords :: [String]
restWords = [String]
tss [String] -> [String] -> [String]
forall a. Eq a => [a] -> [a] -> [a]
\\ [String]
wordsN
                                 in String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> String
unwords [String]
restWords String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
" " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [String]
wordsN)

corr :: Int -> String -> IO Int
corr :: Int -> String -> IO Int
corr Int
pos String
wrdP = do
  let (String
ts, String
us) | Int
pos Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
pos String
wrdP
               | Bool
otherwise = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
wrdP Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
pos) String
wrdP
      twoWords :: String
twoWords = String
ts String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:String
us)
  String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"?:       " String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` String
twoWords
  String
llls <- IO String
getLine
  if String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
llls then Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
pos
  else do
    let tss :: [String]
tss = String -> [String]
words String
llls
        wrd0 :: Int
wrd0 = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
1 (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe ([String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String)
-> ([String] -> [String]) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [String] -> [String]
forall a. Int -> [a] -> [a]
take Int
1 ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [String]
tss)::Maybe Int)
        posN :: Int
posN = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (String -> Maybe Int
forall a. Read a => String -> Maybe a
readMaybe ([String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String)
-> ([String] -> [String]) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [String] -> [String]
forall a. Int -> [a] -> [a]
drop Int
1 ([String] -> [String])
-> ([String] -> [String]) -> [String] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [String] -> [String]
forall a. Int -> [a] -> [a]
take Int
2 ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [String]
tss)::Maybe Int)
    case Int
wrd0 of
      Int
1 -> Int -> String -> IO Int
corr (Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
posN) String
wrdP
      Int
2 -> Int -> String -> IO Int
corr (Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
posN) String
wrdP
      Int
_ -> Int -> String -> IO Int
corr Int
pos String
wrdP

correctionF :: Monad m => Int -> String -> Int -> [String] -> m String
correctionF :: Int -> String -> Int -> [String] -> m String
correctionF Int
pos String
wrdP Int
wordN [String]
wordsN = do
  let (String
ts,String
us) | Int
pos Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
pos String
wrdP
              | Bool
otherwise = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
wrdP Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
pos) String
wrdP
      twoWords :: String
twoWords = String
ts String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:String
us)
      ([String]
wss,[String]
tss) = Int -> [String] -> ([String], [String])
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
wordN Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [String]
wordsN
      kss :: [String]
kss = Int -> [String] -> [String]
forall a. Int -> [a] -> [a]
drop Int
1 [String]
tss
  if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
wss then String -> m String
forall (m :: * -> *) a. Monad m => a -> m a
return (String
twoWords String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:[String] -> String
unwords [String]
kss))
              else String -> m String
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> String
unwords [String]
wss String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:String
twoWords) String -> String -> String
forall a. Monoid a => a -> a -> a
`mappend` (Char
' 'Char -> String -> String
forall a. a -> [a] -> [a]
:[String] -> String
unwords [String]
kss))


{-| Inspired by: 'https://hackage.haskell.org/package/base-4.15.0.0/docs/src/GHC-IO.html#catch'
Reads a textual file given by its 'FilePath' and returns its contents lazily. If there is
some 'IOException' thrown or an empty file then returns just "". Raises an exception for the binary file. -}
readFileIfAny :: FilePath -> IO String
readFileIfAny :: String -> IO String
readFileIfAny String
file = IO String -> (IOException -> IO String) -> IO String
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch (String -> IO String
readFile String
file) (\(IOException
e :: IOException) -> String -> IO String
forall (m :: * -> *) a. Monad m => a -> m a
return String
"")

-------------------------------------------------------------

argsConvertTextual :: String -> [String] -> [String]
argsConvertTextual :: String -> [String] -> [String]
argsConvertTextual String
ts [String]
tss
 | (String -> Bool) -> [String] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
ts) [String]
tss = [String]
tss
 | Bool
otherwise = [String]
tss [String] -> [String] -> [String]
forall a. Monoid a => a -> a -> a
`mappend` [String
ts]
{-# INLINE argsConvertTextual #-}

fullArgsConvertTextual
  :: (String -> Bool) -- ^ The predicate that checks whether the given argument is not a phonetic language word in the representation.
  -> String
  -> String
  -> [String]
  -> [String]
fullArgsConvertTextual :: (String -> Bool) -> String -> String -> [String] -> [String]
fullArgsConvertTextual String -> Bool
p String
textProcessment0 String
lineA [String]
args =
  String -> [String] -> [String]
argsConvertTextual String
textProcessment0 ((String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile String -> Bool
p [String]
args [String] -> [String] -> [String]
forall a. Monoid a => a -> a -> a
`mappend` String -> [String]
words String
lineA)
{-# INLINE fullArgsConvertTextual #-}

-------------------------------------------------------------

fullArgsConvertTextualSimple
  :: (String -> Bool) -- ^ The predicate that checks whether the given argument is not a phonetic language word in the representation.
  -> String
  -> [String]
  -> [String]
fullArgsConvertTextualSimple :: (String -> Bool) -> String -> [String] -> [String]
fullArgsConvertTextualSimple String -> Bool
p String
lineA [String]
args = (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile String -> Bool
p [String]
args [String] -> [String] -> [String]
forall a. Monoid a => a -> a -> a
`mappend` String -> [String]
words String
lineA
{-# INLINE fullArgsConvertTextualSimple #-}