{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wwarn=star-is-type #-}
{-# OPTIONS_GHC -Wno-orphans #-}
-- | This module provides common skeletons for printing tasks
module Control.OutputCapable.Blocks (
  FunctorTrans (..),
  -- * Report monad
  GenericOut (..),
  GenericReportT (..),
  Language (..),
  Out,
  ReportT,
  Report,
  getAllOuts,
  getOutsWithResult,
  toOutput,
  -- * Monad for translations
  GenericLangM (LangM, unLangM),
  LangM',
  LangM,
  Rated,
  -- * Output monad
  GenericOutputCapable (..),
  OutputCapable,
  enumerate,
  abortWith,
  alignOutput,
  combineReports,
  combineTwoReports,
  format,
  recoverFrom,
  recoverWith,
  toAbort,
  -- * Translation
  ArticleToUse (..),
  collapsed,
  english,
  german,
  localise,
  mapLangM,
  multiLang,
  translate,
  translateCode,
  translations,
  -- * Helper functions
  MinimumThreshold (..),
  Punishment (..),
  TargetedCorrect (..),
  ($=<<),
  extendedMultipleChoice,
  multipleChoice,
  multipleChoiceSyntax,
  printSolutionAndAssert,
  printSolutionAndAssertMinimum,
  reRefuse,
  reRefuseLangM,
  singleChoice,
  singleChoiceSyntax,
  continueOrAbort,
  yesNo,
  ) where


import qualified Control.OutputCapable.Blocks.Generic as Generic (
  alignOutput,
  collapsed,
  combineReports,
  combineTwoReports,
  toAbort,
  translate,
  translateCode,
  translations,
  )
import qualified Data.Map as M

import Control.Functor.Trans            (FunctorTrans (lift))
import Control.OutputCapable.Blocks.Generic (
  GenericLangM (..),
  GenericOutputCapable (..),
  GenericReportT (..),
  RunnableOutputCapable (..),
  ($=<<),
  ($>>),
  ($>>=),
  abortWith,
  format,
  mapLangM,
  recoverFrom,
  recoverWith,
  runLangMReport,
  )
import Control.OutputCapable.Blocks.Report (
  GenericOut (..),
  Language (..),
  Out,
  ReportT,
  Report,
  getAllOuts,
  getOutsWithResult,
  toOutput,
  )

import Control.Applicative              (Alternative)
import Control.Monad                    (unless, void, when)
import Control.Monad.State              (State, modify)
import Control.Monad.Writer (
  MonadWriter (tell),
  )
import Data.Containers.ListUtils        (nubOrd)
import Data.Data                        (Data)
import Data.Foldable                    (for_, traverse_)
import Data.Map                         (Map,foldrWithKey)
import Data.Maybe                       (fromMaybe, isJust)
import Data.Ratio                       ((%))
import GHC.Generics                     (Generic)

{-|
If argument is 'True',
it will continue after assertion,
otherwise it will stop if assertion fails.
-}
continueOrAbort :: OutputCapable m => Bool -> Bool -> LangM m -> LangM m
continueOrAbort :: forall (m :: * -> *).
OutputCapable m =>
Bool -> Bool -> LangM m -> LangM m
continueOrAbort Bool
True  = Bool -> LangM m -> LangM m
forall (m :: * -> *). OutputCapable m => Bool -> LangM m -> LangM m
yesNo
continueOrAbort Bool
False = Bool -> LangM m -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
Bool -> GenericLangM l m () -> GenericLangM l m ()
assertion

{-|
In contrast to 'assertion' it will only indicate that a check was performed
and its result.
However, it will not abort.
-}
yesNo :: OutputCapable m => Bool -> LangM m -> LangM m
yesNo :: forall (m :: * -> *). OutputCapable m => Bool -> LangM m -> LangM m
yesNo Bool
p LangM m
q = do
  LangM m -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
paragraph LangM m
q
  LangM m -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
paragraph (LangM m -> LangM m) -> LangM m -> LangM m
forall a b. (a -> b) -> a -> b
$ LangM m -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
indent (LangM m -> LangM m) -> LangM m -> LangM m
forall a b. (a -> b) -> a -> b
$ (Language -> String) -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
(l -> String) -> GenericLangM l m ()
translatedCode ((Language -> String) -> LangM m)
-> (Language -> String) -> LangM m
forall a b. (a -> b) -> a -> b
$ (Language -> Map Language String -> String)
-> Map Language String -> Language -> String
forall a b c. (a -> b -> c) -> b -> a -> c
flip Language -> Map Language String -> String
localise (Map Language String -> Language -> String)
-> Map Language String -> Language -> String
forall a b. (a -> b) -> a -> b
$ State (Map Language String) () -> Map Language String
forall l a. State (Map l a) () -> Map l a
translations (State (Map Language String) () -> Map Language String)
-> State (Map Language String) () -> Map Language String
forall a b. (a -> b) -> a -> b
$
      if Bool
p
      then do
        String -> State (Map Language String) ()
english String
"Yes."
        String -> State (Map Language String) ()
german String
"Ja."
      else do
        String -> State (Map Language String) ()
english String
"No."
        String -> State (Map Language String) ()
german String
"Nein."
  pure ()

{-|
A 'Rational' number indicating the minimal threshold.
-}
newtype MinimumThreshold = MinimumThreshold {
  MinimumThreshold -> Rational
unMinimumThreshold :: Rational
  }

{-|
A 'Rational' number indicating the punishment.
-}
newtype Punishment = Punishment {
  Punishment -> Rational
unPunishment :: Rational
  }

{-|
A 'Int' number indicating expected correct answers.
-}
newtype TargetedCorrect = TargetedCorrect {
  TargetedCorrect -> Int
unTargetedCorrect :: Int
  }

{-|
Outputs feedback on syntax of a multiple choice submission.
Depending on chosen parameters it might reject the submission.
-}
multipleChoiceSyntax
  :: (OutputCapable m, Ord a, Show a)
  => Bool
  -- ^ whether to continue after check (i.e. do not reject wrong answers)
  -> [a]
  -- ^ possible answers
  -> [a]
  -- ^ the submission to evaluate
  -> LangM m
multipleChoiceSyntax :: forall (m :: * -> *) a.
(OutputCapable m, Ord a, Show a) =>
Bool -> [a] -> [a] -> LangM m
multipleChoiceSyntax Bool
withSolution [a]
options =
  (a -> GenericLangM Language m ())
-> [a] -> GenericLangM Language m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Bool -> [a] -> a -> GenericLangM Language m ()
forall (m :: * -> *) a.
(OutputCapable m, Eq a, Show a) =>
Bool -> [a] -> a -> LangM m
singleChoiceSyntax Bool
withSolution [a]
options) ([a] -> GenericLangM Language m ())
-> ([a] -> [a]) -> [a] -> GenericLangM Language m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> [a]
forall a. Ord a => [a] -> [a]
nubOrd

{-|
Evaluates multiple choice submissions
by rejecting correctness below 50 percent.
(see 'extendedMultipleChoice')
-}
multipleChoice
  :: (OutputCapable m, Ord a)
  => ArticleToUse
  -- ^ indicating if multiple different solutions could be possible
  -> Map Language String
  -- ^ what is asked for
  -> Maybe String
  -- ^ the correct solution to show
  -> Map a Bool
  -- ^ possible answers and if they are correct
  -> [a]
  -- ^ the submission to evaluate
  -> Rated m
multipleChoice :: forall (m :: * -> *) a.
(OutputCapable m, Ord a) =>
ArticleToUse
-> Map Language String
-> Maybe String
-> Map a Bool
-> [a]
-> Rated m
multipleChoice ArticleToUse
articleToUse Map Language String
what Maybe String
solutionString Map a Bool
solution =
  MinimumThreshold
-> Punishment
-> TargetedCorrect
-> ArticleToUse
-> Map Language String
-> Maybe String
-> Map a Bool
-> Map a Bool
-> Rated m
forall (m :: * -> *) a.
(OutputCapable m, Ord a) =>
MinimumThreshold
-> Punishment
-> TargetedCorrect
-> ArticleToUse
-> Map Language String
-> Maybe String
-> Map a Bool
-> Map a Bool
-> Rated m
extendedMultipleChoice
  (Rational -> MinimumThreshold
MinimumThreshold (Integer
1 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
2))
  (Rational -> Punishment
Punishment Rational
0)
  (Int -> TargetedCorrect
TargetedCorrect (Map a Bool -> Int
forall a. Map a a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Map a Bool
solution))
  ArticleToUse
articleToUse
  Map Language String
what
  Maybe String
solutionString
  Map a Bool
solution
  (Map a Bool -> Rated m) -> ([a] -> Map a Bool) -> [a] -> Rated m
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Map a Bool -> Map a Bool) -> Map a Bool -> [a] -> Map a Bool
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (a -> Bool -> Map a Bool -> Map a Bool
forall k a. Ord k => k -> a -> Map k a -> Map k a
`M.insert` Bool
True) ((Bool -> Bool) -> Map a Bool -> Map a Bool
forall a k. (a -> Bool) -> Map k a -> Map k a
M.filter Bool -> Bool
not Map a Bool
solution)

{-|
Evaluates multiple choice submissions
by rejecting correctness below a minimum threshold.


The following preconditions need to hold before calling this function
but are not checked:

 * targeted correct is at least one
   and not larger than the amount of possible answers
-}
extendedMultipleChoice
  :: (OutputCapable m, Ord a)
  => MinimumThreshold
  -- ^ the minimum threshold of achieved points
  -> Punishment
  -- ^ points to subtract per wrong answer
  -> TargetedCorrect
  -- ^ how many correct answers have to be given within the submission
  -- in order to achieve full points
  -> ArticleToUse
  -- ^ indicating if multiple different solutions could be possible
  -> Map Language String
  -- ^ what is asked for
  -> Maybe String
  -- ^ the correct solution to show
  -> Map a Bool
  -- ^ possible answers and if they are correct
  -> Map a Bool
  -- ^ the submission to evaluate
  -> Rated m
extendedMultipleChoice :: forall (m :: * -> *) a.
(OutputCapable m, Ord a) =>
MinimumThreshold
-> Punishment
-> TargetedCorrect
-> ArticleToUse
-> Map Language String
-> Maybe String
-> Map a Bool
-> Map a Bool
-> Rated m
extendedMultipleChoice
  MinimumThreshold
minimumPoints
  Punishment
punishment
  TargetedCorrect
targeted
  ArticleToUse
articleToUse
  Map Language String
what
  Maybe String
optionalSolutionString
  Map a Bool
solution
  Map a Bool
choices
  = LangM m
correctnessCheck
  LangM m -> LangM m -> LangM m
forall a b.
GenericLangM Language m a
-> GenericLangM Language m b -> GenericLangM Language m b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> LangM m
exhaustivenessCheck
  LangM m
-> GenericLangM Language m Rational
-> GenericLangM Language m Rational
forall a b.
GenericLangM Language m a
-> GenericLangM Language m b -> GenericLangM Language m b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> MinimumThreshold
-> ArticleToUse
-> Maybe String
-> Rational
-> GenericLangM Language m Rational
forall (m :: * -> *).
OutputCapable m =>
MinimumThreshold
-> ArticleToUse -> Maybe String -> Rational -> Rated m
printSolutionAndAssertMinimum
    MinimumThreshold
minimumPoints
    ArticleToUse
articleToUse
    Maybe String
optionalSolutionString
    Rational
points
  where
    madeUp :: Map a Bool
madeUp = Map a Bool -> Map a Bool -> Map a Bool
forall k a b. Ord k => Map k a -> Map k b -> Map k a
M.difference Map a Bool
choices Map a Bool
solution
    chosenTrue :: Map a Bool
chosenTrue = Map a Bool -> Map a Bool -> Map a Bool
forall k a b. Ord k => Map k a -> Map k b -> Map k a
M.intersection Map a Bool
solution (Map a Bool -> Map a Bool) -> Map a Bool -> Map a Bool
forall a b. (a -> b) -> a -> b
$ (Bool -> Bool) -> Map a Bool -> Map a Bool
forall a k. (a -> Bool) -> Map k a -> Map k a
M.filter Bool -> Bool
forall a. a -> a
id Map a Bool
choices
    isCorrect :: Bool
isCorrect = Map a Bool -> Bool
forall k a. Map k a -> Bool
M.null Map a Bool
madeUp Bool -> Bool -> Bool
&& Map a Bool -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and Map a Bool
chosenTrue
    points :: Rational
points = Punishment
-> TargetedCorrect -> Map a Bool -> Map a Bool -> Rational
forall k.
Ord k =>
Punishment
-> TargetedCorrect -> Map k Bool -> Map k Bool -> Rational
gradeMultipleChoice Punishment
punishment TargetedCorrect
targeted Map a Bool
solution Map a Bool
choices
    correctnessCheck :: LangM m
correctnessCheck = Bool -> LangM m -> LangM m
forall (m :: * -> *). OutputCapable m => Bool -> LangM m -> LangM m
yesNo Bool
isCorrect (LangM m -> LangM m) -> LangM m -> LangM m
forall a b. (a -> b) -> a -> b
$ [(Language, String)] -> LangM m
forall (m :: * -> *).
OutputCapable m =>
[(Language, String)] -> LangM m
multiLang [
      (Language
English, String
"All indicated " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Language -> Map Language String -> String
localise Language
English Map Language String
what String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" are correct?"),
      (Language
German, String
"Alle angegebenen " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Language -> Map Language String -> String
localise Language
German Map Language String
what String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" sind korrekt?")
      ]
    answers :: Map a Bool
answers = (Bool -> Bool -> Bool) -> Map a Bool -> Map a Bool -> Map a Bool
forall k a b c.
Ord k =>
(a -> b -> c) -> Map k a -> Map k b -> Map k c
M.intersectionWith Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
(==) Map a Bool
solution Map a Bool
choices
    isComplete :: Bool
isComplete = Map a Bool -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and Map a Bool
answers Bool -> Bool -> Bool
&& Map a Bool -> Int
forall a. Map a a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Map a Bool
answers Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= TargetedCorrect -> Int
unTargetedCorrect TargetedCorrect
targeted
    exhaustivenessCheck :: LangM m
exhaustivenessCheck = Bool -> LangM m -> LangM m
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isCorrect
      (LangM m -> LangM m) -> LangM m -> LangM m
forall a b. (a -> b) -> a -> b
$ Bool -> LangM m -> LangM m
forall (m :: * -> *). OutputCapable m => Bool -> LangM m -> LangM m
yesNo Bool
isComplete (LangM m -> LangM m) -> LangM m -> LangM m
forall a b. (a -> b) -> a -> b
$ [(Language, String)] -> LangM m
forall (m :: * -> *).
OutputCapable m =>
[(Language, String)] -> LangM m
multiLang [
      (Language
English, String
"The indicated " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Language -> Map Language String -> String
localise Language
English Map Language String
what String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" are exhaustive?"),
      (Language
German, String
"Die angegebenen " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Language -> Map Language String -> String
localise Language
German Map Language String
what String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" sind vollzählig?")
      ]

{-|
Calculates points based on the portion of correct choices.

Note that invalid entries within the submission list
(i.e. which are not covered by the possible answers map)
are punished like wrong answers.

The following preconditions need to hold before calling this function
but are not checked:

 * targeted correct is at least one
   and not larger than the amount of possible answers
-}
gradeMultipleChoice
  :: Ord k
  => Punishment
  -- ^ how many points to subtract per wrong answer given
  -> TargetedCorrect
  -- ^ how many of all possible correct answers are considered exhaustive
  -> Map k Bool
  -- ^ possible answers and if they are correct
  -> Map k Bool
  -- ^ submission
  -> Rational
gradeMultipleChoice :: forall k.
Ord k =>
Punishment
-> TargetedCorrect -> Map k Bool -> Map k Bool -> Rational
gradeMultipleChoice Punishment {Rational
unPunishment :: Punishment -> Rational
unPunishment :: Rational
..} TargetedCorrect {Int
unTargetedCorrect :: TargetedCorrect -> Int
unTargetedCorrect :: Int
..} Map k Bool
solution Map k Bool
choices =
  Rational -> Rational -> Rational
forall a. Ord a => a -> a -> a
max Rational
0
    (Rational -> Rational) -> Rational -> Rational
forall a b. (a -> b) -> a -> b
$ Rational -> Rational -> Rational
forall a. Ord a => a -> a -> a
min Rational
1 (Int -> Integer
forall a. Integral a => a -> Integer
toInteger (Map k Bool -> Int
forall a. Map k a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Map k Bool
correct) Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
unTargetedCorrect)
    Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
- Int -> Integer
forall a. Integral a => a -> Integer
toInteger (Map k Bool -> Int
forall a. Map k a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Map k Bool
incorrect) Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
1 Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
unPunishment
  where
    (Map k Bool
correct, Map k Bool
incorrect) =
      (k -> Bool -> Bool) -> Map k Bool -> (Map k Bool, Map k Bool)
forall k a. (k -> a -> Bool) -> Map k a -> (Map k a, Map k a)
M.partitionWithKey (\k
k -> (Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
== k -> Map k Bool -> Maybe Bool
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup k
k Map k Bool
solution) (Maybe Bool -> Bool) -> (Bool -> Maybe Bool) -> Bool -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Maybe Bool
forall a. a -> Maybe a
Just) Map k Bool
choices


{-|
Use the specified article.
-}
data ArticleToUse
  = DefiniteArticle
  -- ^ use definite article(s)
  | IndefiniteArticle
  -- ^ use indefinite article(s)
  deriving (ArticleToUse -> ArticleToUse -> Bool
(ArticleToUse -> ArticleToUse -> Bool)
-> (ArticleToUse -> ArticleToUse -> Bool) -> Eq ArticleToUse
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ArticleToUse -> ArticleToUse -> Bool
== :: ArticleToUse -> ArticleToUse -> Bool
$c/= :: ArticleToUse -> ArticleToUse -> Bool
/= :: ArticleToUse -> ArticleToUse -> Bool
Eq, (forall x. ArticleToUse -> Rep ArticleToUse x)
-> (forall x. Rep ArticleToUse x -> ArticleToUse)
-> Generic ArticleToUse
forall x. Rep ArticleToUse x -> ArticleToUse
forall x. ArticleToUse -> Rep ArticleToUse x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ArticleToUse -> Rep ArticleToUse x
from :: forall x. ArticleToUse -> Rep ArticleToUse x
$cto :: forall x. Rep ArticleToUse x -> ArticleToUse
to :: forall x. Rep ArticleToUse x -> ArticleToUse
Generic, ReadPrec [ArticleToUse]
ReadPrec ArticleToUse
Int -> ReadS ArticleToUse
ReadS [ArticleToUse]
(Int -> ReadS ArticleToUse)
-> ReadS [ArticleToUse]
-> ReadPrec ArticleToUse
-> ReadPrec [ArticleToUse]
-> Read ArticleToUse
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS ArticleToUse
readsPrec :: Int -> ReadS ArticleToUse
$creadList :: ReadS [ArticleToUse]
readList :: ReadS [ArticleToUse]
$creadPrec :: ReadPrec ArticleToUse
readPrec :: ReadPrec ArticleToUse
$creadListPrec :: ReadPrec [ArticleToUse]
readListPrec :: ReadPrec [ArticleToUse]
Read, Int -> ArticleToUse -> String -> String
[ArticleToUse] -> String -> String
ArticleToUse -> String
(Int -> ArticleToUse -> String -> String)
-> (ArticleToUse -> String)
-> ([ArticleToUse] -> String -> String)
-> Show ArticleToUse
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> ArticleToUse -> String -> String
showsPrec :: Int -> ArticleToUse -> String -> String
$cshow :: ArticleToUse -> String
show :: ArticleToUse -> String
$cshowList :: [ArticleToUse] -> String -> String
showList :: [ArticleToUse] -> String -> String
Show, Typeable ArticleToUse
Typeable ArticleToUse =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> ArticleToUse -> c ArticleToUse)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c ArticleToUse)
-> (ArticleToUse -> Constr)
-> (ArticleToUse -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c ArticleToUse))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c ArticleToUse))
-> ((forall b. Data b => b -> b) -> ArticleToUse -> ArticleToUse)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> ArticleToUse -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> ArticleToUse -> r)
-> (forall u. (forall d. Data d => d -> u) -> ArticleToUse -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> ArticleToUse -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse)
-> Data ArticleToUse
ArticleToUse -> Constr
ArticleToUse -> DataType
(forall b. Data b => b -> b) -> ArticleToUse -> ArticleToUse
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> ArticleToUse -> u
forall u. (forall d. Data d => d -> u) -> ArticleToUse -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ArticleToUse -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ArticleToUse -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ArticleToUse
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ArticleToUse -> c ArticleToUse
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ArticleToUse)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c ArticleToUse)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ArticleToUse -> c ArticleToUse
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ArticleToUse -> c ArticleToUse
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ArticleToUse
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ArticleToUse
$ctoConstr :: ArticleToUse -> Constr
toConstr :: ArticleToUse -> Constr
$cdataTypeOf :: ArticleToUse -> DataType
dataTypeOf :: ArticleToUse -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ArticleToUse)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ArticleToUse)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c ArticleToUse)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c ArticleToUse)
$cgmapT :: (forall b. Data b => b -> b) -> ArticleToUse -> ArticleToUse
gmapT :: (forall b. Data b => b -> b) -> ArticleToUse -> ArticleToUse
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ArticleToUse -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ArticleToUse -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ArticleToUse -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ArticleToUse -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> ArticleToUse -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> ArticleToUse -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ArticleToUse -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ArticleToUse -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ArticleToUse -> m ArticleToUse
Data)

{-|
Outputs the correct solution (if given)
when achieved points are less than 100 percent.
No points are distributed if not at least 50 percent are achieved.
(see 'printSolutionAndAssertMinimum')
-}
printSolutionAndAssert
  :: OutputCapable m
  => ArticleToUse
  -- ^ indicating if multiple different solutions could be possible
  -> Maybe String
  -- ^ the correct solution to show
  -> Rational
  -- ^ points achieved
  -> Rated m
printSolutionAndAssert :: forall (m :: * -> *).
OutputCapable m =>
ArticleToUse -> Maybe String -> Rational -> Rated m
printSolutionAndAssert = MinimumThreshold
-> ArticleToUse -> Maybe String -> Rational -> Rated m
forall (m :: * -> *).
OutputCapable m =>
MinimumThreshold
-> ArticleToUse -> Maybe String -> Rational -> Rated m
printSolutionAndAssertMinimum
  (MinimumThreshold
 -> ArticleToUse -> Maybe String -> Rational -> Rated m)
-> MinimumThreshold
-> ArticleToUse
-> Maybe String
-> Rational
-> Rated m
forall a b. (a -> b) -> a -> b
$ Rational -> MinimumThreshold
MinimumThreshold (Integer
1 Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% Integer
2)

{-|
Outputs the correct solution (if given)
when achieved points are less than 100 percent.
No points are distributed if they do not reach the minimum threshold.
-}
printSolutionAndAssertMinimum
  :: OutputCapable m
  => MinimumThreshold
  -- ^ the minimum threshold of achieved points
  -> ArticleToUse
  -- ^ indicating if multiple different solutions could be possible
  -> Maybe String
  -- ^ the correct solution to show
  -> Rational
  -- ^ points achieved
  -> Rated m
printSolutionAndAssertMinimum :: forall (m :: * -> *).
OutputCapable m =>
MinimumThreshold
-> ArticleToUse -> Maybe String -> Rational -> Rated m
printSolutionAndAssertMinimum
  MinimumThreshold
minimumPoints
  ArticleToUse
articleToUse
  Maybe String
optionalSolutionString
  Rational
points
  = do
  Maybe String
-> (String -> GenericLangM Language m ())
-> GenericLangM Language m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Maybe String
optionalSolutionString (\String
solutionString ->
    Bool -> GenericLangM Language m () -> GenericLangM Language m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Rational
points Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
/= Rational
1) (GenericLangM Language m () -> GenericLangM Language m ())
-> GenericLangM Language m () -> GenericLangM Language m ()
forall a b. (a -> b) -> a -> b
$ GenericLangM Language m () -> GenericLangM Language m ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
paragraph (GenericLangM Language m () -> GenericLangM Language m ())
-> GenericLangM Language m () -> GenericLangM Language m ()
forall a b. (a -> b) -> a -> b
$ do
      State (Map Language String) () -> GenericLangM Language m ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
State (Map l String) () -> GenericLangM l m ()
translate (State (Map Language String) () -> GenericLangM Language m ())
-> State (Map Language String) () -> GenericLangM Language m ()
forall a b. (a -> b) -> a -> b
$ case ArticleToUse
articleToUse of
        ArticleToUse
DefiniteArticle -> do
          String -> State (Map Language String) ()
english String
"The correct solution is:"
          String -> State (Map Language String) ()
german String
"Die korrekte Lösung ist:"
        ArticleToUse
IndefiniteArticle -> do
          String -> State (Map Language String) ()
english String
"A correct solution is:"
          String -> State (Map Language String) ()
german String
"Eine korrekte Lösung ist:"
      String -> GenericLangM Language m ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
String -> GenericLangM l m ()
code String
solutionString
      pure ()
    )
  Bool -> GenericLangM Language m () -> GenericLangM Language m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Rational
points Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
>= MinimumThreshold -> Rational
unMinimumThreshold MinimumThreshold
minimumPoints) (GenericLangM Language m () -> GenericLangM Language m ())
-> GenericLangM Language m () -> GenericLangM Language m ()
forall a b. (a -> b) -> a -> b
$ GenericLangM Language m () -> GenericLangM Language m ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
refuse (GenericLangM Language m () -> GenericLangM Language m ())
-> GenericLangM Language m () -> GenericLangM Language m ()
forall a b. (a -> b) -> a -> b
$ () -> GenericLangM Language m ()
forall a. a -> GenericLangM Language m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
  return Rational
points

{-|
Outputs feedback on syntax of a single choice submission.
Depending on chosen parameters it might reject the submission.
-}
singleChoiceSyntax
  :: (OutputCapable m, Eq a, Show a)
  => Bool
  -- ^ whether to continue after check (i.e. do not reject wrong answers)
  -> [a]
  -- ^ possible answers
  -> a
  -- ^ the submission to evaluate
  -> LangM m
singleChoiceSyntax :: forall (m :: * -> *) a.
(OutputCapable m, Eq a, Show a) =>
Bool -> [a] -> a -> LangM m
singleChoiceSyntax Bool
withSolution [a]
options a
choice =
  let assert :: Bool -> LangM m -> LangM m
assert = Bool -> Bool -> LangM m -> LangM m
forall (m :: * -> *).
OutputCapable m =>
Bool -> Bool -> LangM m -> LangM m
continueOrAbort Bool
withSolution
  in Bool -> LangM m -> LangM m
assert (a
choice a -> [a] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [a]
options) (LangM m -> LangM m) -> LangM m -> LangM m
forall a b. (a -> b) -> a -> b
$ State (Map Language String) () -> LangM m
forall l (m :: * -> *).
GenericOutputCapable l m =>
State (Map l String) () -> GenericLangM l m ()
translate (State (Map Language String) () -> LangM m)
-> State (Map Language String) () -> LangM m
forall a b. (a -> b) -> a -> b
$ do
    let c :: String
c = a -> String
forall a. Show a => a -> String
show a
choice
    String -> State (Map Language String) ()
english (String -> State (Map Language String) ())
-> String -> State (Map Language String) ()
forall a b. (a -> b) -> a -> b
$ String
"Chosen option " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c  String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is available?"
    String -> State (Map Language String) ()
german (String -> State (Map Language String) ())
-> String -> State (Map Language String) ()
forall a b. (a -> b) -> a -> b
$ String
"Gewählte Option " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
c String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" ist verfügbar?"

{-|
Outputs feedback and rates a single choice submission.
-}
singleChoice
  :: (OutputCapable m, Eq a)
  => ArticleToUse
  -- ^ indicating if multiple different solutions could be possible
  -> Map Language String
  -- ^ what is asked for
  -> Maybe String
  -- ^ the correct solution to show
  -> a
  -- ^ the correct answer
  -> a
  -- ^ the submission to evaluate
  -> LangM m
singleChoice :: forall (m :: * -> *) a.
(OutputCapable m, Eq a) =>
ArticleToUse
-> Map Language String -> Maybe String -> a -> a -> LangM m
singleChoice ArticleToUse
articleToUse Map Language String
what Maybe String
optionalSolutionString a
solution a
choice = GenericLangM Language m Rational -> GenericLangM Language m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (GenericLangM Language m Rational -> GenericLangM Language m ())
-> GenericLangM Language m Rational -> GenericLangM Language m ()
forall a b. (a -> b) -> a -> b
$
  GenericLangM Language m ()
checkCorrect
  GenericLangM Language m ()
-> GenericLangM Language m Rational
-> GenericLangM Language m Rational
forall a b.
GenericLangM Language m a
-> GenericLangM Language m b -> GenericLangM Language m b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ArticleToUse
-> Maybe String -> Rational -> GenericLangM Language m Rational
forall (m :: * -> *).
OutputCapable m =>
ArticleToUse -> Maybe String -> Rational -> Rated m
printSolutionAndAssert ArticleToUse
articleToUse Maybe String
optionalSolutionString Rational
points
  where
    correct :: Bool
correct = a
solution a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
choice
    points :: Rational
points = if Bool
correct then Rational
1 else Rational
0
    assert :: Bool -> GenericLangM Language m () -> GenericLangM Language m ()
assert = Bool
-> Bool -> GenericLangM Language m () -> GenericLangM Language m ()
forall (m :: * -> *).
OutputCapable m =>
Bool -> Bool -> LangM m -> LangM m
continueOrAbort (Bool
 -> Bool
 -> GenericLangM Language m ()
 -> GenericLangM Language m ())
-> Bool
-> Bool
-> GenericLangM Language m ()
-> GenericLangM Language m ()
forall a b. (a -> b) -> a -> b
$ Maybe String -> Bool
forall a. Maybe a -> Bool
isJust Maybe String
optionalSolutionString
    checkCorrect :: GenericLangM Language m ()
checkCorrect = Bool -> GenericLangM Language m () -> GenericLangM Language m ()
assert Bool
correct (GenericLangM Language m () -> GenericLangM Language m ())
-> GenericLangM Language m () -> GenericLangM Language m ()
forall a b. (a -> b) -> a -> b
$ [(Language, String)] -> GenericLangM Language m ()
forall (m :: * -> *).
OutputCapable m =>
[(Language, String)] -> LangM m
multiLang [
      (Language
English, String
"Chosen " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Language -> Map Language String -> String
localise Language
English Map Language String
what String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is correct?"),
      (Language
German, String
"Der/die/das gewählte " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Language -> Map Language String -> String
localise Language
German Map Language String
what String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" ist korrekt?")]

{-|
Append some remarks after some rating function.
But re-reject afterwards (if it was rejected by the rating function).
-}
reRefuse
  :: (Alternative m, Monad m, OutputCapable m)
  => Rated m
  -> LangM m
  -> Rated m
reRefuse :: forall (m :: * -> *).
(Alternative m, Monad m, OutputCapable m) =>
Rated m -> LangM m -> Rated m
reRefuse = Rational
-> GenericLangM Language m Rational
-> GenericLangM Language m ()
-> GenericLangM Language m Rational
forall (m :: * -> *) l b a.
(Alternative m, Monad m, GenericOutputCapable l m) =>
b -> GenericLangM l m b -> GenericLangM l m a -> GenericLangM l m b
reRefuseWith Rational
0

{-|
Append some remarks after a potential rejection.
But re-reject afterwards (if it was rejected before).

@since 0.4.0.3
-}
reRefuseLangM
  :: (Alternative m, Monad m, OutputCapable m)
  => LangM m
  -> LangM m
  -> LangM m
reRefuseLangM :: forall (m :: * -> *).
(Alternative m, Monad m, OutputCapable m) =>
LangM m -> LangM m -> LangM m
reRefuseLangM = ()
-> GenericLangM Language m ()
-> GenericLangM Language m ()
-> GenericLangM Language m ()
forall (m :: * -> *) l b a.
(Alternative m, Monad m, GenericOutputCapable l m) =>
b -> GenericLangM l m b -> GenericLangM l m a -> GenericLangM l m b
reRefuseWith ()

{-|
Append some remarks after a potential rejection.
But re-reject afterwards (if it was rejected before).
-}
reRefuseWith :: (Alternative m, Monad m, GenericOutputCapable l m)
  => b
  -> GenericLangM l m b
  -> GenericLangM l m a
  -> GenericLangM l m b
reRefuseWith :: forall (m :: * -> *) l b a.
(Alternative m, Monad m, GenericOutputCapable l m) =>
b -> GenericLangM l m b -> GenericLangM l m a -> GenericLangM l m b
reRefuseWith b
bottom GenericLangM l m b
xs GenericLangM l m a
ys =
  GenericLangM l m b
-> GenericLangM l m b
-> GenericLangM l m (Either (GenericLangM l m b) b)
forall (m :: * -> *) a l b.
Alternative m =>
a -> GenericLangM l m b -> GenericLangM l m (Either a b)
recoverWith (b -> GenericLangM l m b
forall a. a -> GenericLangM l m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
bottom) GenericLangM l m b
xs
    GenericLangM l m (Either (GenericLangM l m b) b)
-> (Either (GenericLangM l m b) b -> GenericLangM l m b)
-> GenericLangM l m b
forall (m :: * -> *) l a b.
Monad m =>
GenericLangM l m a
-> (a -> GenericLangM l m b) -> GenericLangM l m b
$>>= \Either (GenericLangM l m b) b
x -> GenericLangM l m a
ys
    GenericLangM l m a -> GenericLangM l m b -> GenericLangM l m b
forall (m :: * -> *) l a b.
Monad m =>
GenericLangM l m a -> GenericLangM l m b -> GenericLangM l m b
$>> (GenericLangM l m b -> GenericLangM l m b)
-> (b -> GenericLangM l m b)
-> Either (GenericLangM l m b) b
-> GenericLangM l m b
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (GenericLangM l m () -> GenericLangM l m ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
refuse (() -> GenericLangM l m ()
forall a. a -> GenericLangM l m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) GenericLangM l m () -> GenericLangM l m b -> GenericLangM l m b
forall a b.
GenericLangM l m a -> GenericLangM l m b -> GenericLangM l m b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*>) b -> GenericLangM l m b
forall a. a -> GenericLangM l m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Either (GenericLangM l m b) b
x

multiLang :: OutputCapable m => [(Language, String)] -> LangM m
multiLang :: forall (m :: * -> *).
OutputCapable m =>
[(Language, String)] -> LangM m
multiLang [(Language, String)]
xs = (Language -> String) -> GenericLangM Language m ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
(l -> String) -> GenericLangM l m ()
translated ((Language -> String) -> GenericLangM Language m ())
-> (Language -> String) -> GenericLangM Language m ()
forall a b. (a -> b) -> a -> b
$ \Language
l ->
  String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"" (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ Language -> [(Language, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup Language
l [(Language, String)]
xs

localise :: Language -> Map Language String -> String
localise :: Language -> Map Language String -> String
localise Language
l Map Language String
lm = String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
nonExistent (Maybe String -> String) -> Maybe String -> String
forall a b. (a -> b) -> a -> b
$ Language -> Map Language String -> Maybe String
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Language
l Map Language String
lm
  where
    nonExistent :: String
nonExistent
      | Map Language String -> Bool
forall a. Map Language a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Map Language String
lm   = String -> String
forall a. HasCallStack => String -> a
error String
"missing translation"
      | Bool
otherwise = (Language, String) -> String
forall a b. (a, b) -> b
snd ((Language, String) -> String) -> (Language, String) -> String
forall a b. (a -> b) -> a -> b
$ Map Language String -> (Language, String)
forall k a. Map k a -> (k, a)
M.findMin Map Language String
lm

{-|
This is a more specific version of 'Generic.translate'
which enforces the usage pattern.
You should always prefer this version over the generic.
-}
translate
  :: GenericOutputCapable l m
  => State (Map l String) ()
  -> GenericLangM l m ()
translate :: forall l (m :: * -> *).
GenericOutputCapable l m =>
State (Map l String) () -> GenericLangM l m ()
translate = State (Map l String) () -> GenericLangM l m ()
forall language (m :: * -> *) a.
GenericOutputCapable language m =>
State (Map language String) a -> GenericLangM language m ()
Generic.translate

{-|
This is a more specific version of 'Generic.translateCode'
which enforces the usage pattern.
You should always prefer this version over the generic.
-}
translateCode
  :: GenericOutputCapable l m
  => State (Map l String) ()
  -> GenericLangM l m ()
translateCode :: forall l (m :: * -> *).
GenericOutputCapable l m =>
State (Map l String) () -> GenericLangM l m ()
translateCode = State (Map l String) () -> GenericLangM l m ()
forall language (m :: * -> *) a.
GenericOutputCapable language m =>
State (Map language String) a -> GenericLangM language m ()
Generic.translateCode

{-|
This is a more specific version of 'Generic.translations'
which enforces the usage pattern.
You should always prefer this version over the generic.
-}
translations :: State (Map l a) () -> Map l a
translations :: forall l a. State (Map l a) () -> Map l a
translations = State (Map l a) () -> Map l a
forall language a1 a2.
State (Map language a1) a2 -> Map language a1
Generic.translations

{-|
This is a more specific version of 'Generic.collapsed'
which enforces the usage pattern.
You should always prefer this version over the generic.
-}
collapsed
  :: GenericOutputCapable l m
  => Bool
  -> State (Map l String) ()
  -> GenericLangM l m ()
  -> GenericLangM l m ()
collapsed :: forall l (m :: * -> *).
GenericOutputCapable l m =>
Bool
-> State (Map l String) ()
-> GenericLangM l m ()
-> GenericLangM l m ()
collapsed = Bool
-> State (Map l String) ()
-> GenericLangM l m ()
-> GenericLangM l m ()
forall language (m :: * -> *) a1.
GenericOutputCapable language m =>
Bool
-> State (Map language String) a1
-> GenericLangM language m ()
-> GenericLangM language m ()
Generic.collapsed

{-|
Provide an English translation
to be appended after previous English translations.
-}
english :: String -> State (Map Language String) ()
english :: String -> State (Map Language String) ()
english = (Map Language String -> Map Language String)
-> State (Map Language String) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((Map Language String -> Map Language String)
 -> State (Map Language String) ())
-> (String -> Map Language String -> Map Language String)
-> String
-> State (Map Language String) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String -> String)
-> Language -> String -> Map Language String -> Map Language String
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
M.insertWith ((String -> String -> String) -> String -> String -> String
forall a b c. (a -> b -> c) -> b -> a -> c
flip String -> String -> String
forall a. [a] -> [a] -> [a]
(++)) Language
English

{-|
Provide an German translation
to be appended after previous German translations.
-}
german :: String -> State (Map Language String) ()
german :: String -> State (Map Language String) ()
german = (Map Language String -> Map Language String)
-> State (Map Language String) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((Map Language String -> Map Language String)
 -> State (Map Language String) ())
-> (String -> Map Language String -> Map Language String)
-> String
-> State (Map Language String) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String -> String)
-> Language -> String -> Map Language String -> Map Language String
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
M.insertWith ((String -> String -> String) -> String -> String -> String
forall a b c. (a -> b -> c) -> b -> a -> c
flip String -> String -> String
forall a. [a] -> [a] -> [a]
(++)) Language
German

type LangM' m a = GenericLangM Language m a
type LangM m = LangM' m ()
type Rated m = LangM' m Rational

enumerate
  :: GenericOutputCapable l m
  => (k -> String)
  -> (a -> String)
  -> Map k a
  -> GenericLangM l m ()
enumerate :: forall l (m :: * -> *) k a.
GenericOutputCapable l m =>
(k -> String) -> (a -> String) -> Map k a -> GenericLangM l m ()
enumerate k -> String
f a -> String
g Map k a
m = (k -> GenericLangM l m ())
-> [(k, GenericLangM l m ())] -> GenericLangM l m ()
forall a.
(a -> GenericLangM l m ())
-> [(a, GenericLangM l m ())] -> GenericLangM l m ()
forall l (m :: * -> *) a.
GenericOutputCapable l m =>
(a -> GenericLangM l m ())
-> [(a, GenericLangM l m ())] -> GenericLangM l m ()
enumerateM (String -> GenericLangM l m ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
String -> GenericLangM l m ()
text (String -> GenericLangM l m ())
-> (k -> String) -> k -> GenericLangM l m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. k -> String
f) (Map k (GenericLangM l m ()) -> [(k, GenericLangM l m ())]
forall k a. Map k a -> [(k, a)]
M.toList (Map k (GenericLangM l m ()) -> [(k, GenericLangM l m ())])
-> Map k (GenericLangM l m ()) -> [(k, GenericLangM l m ())]
forall a b. (a -> b) -> a -> b
$ String -> GenericLangM l m ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
String -> GenericLangM l m ()
text (String -> GenericLangM l m ())
-> (a -> String) -> a -> GenericLangM l m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
g (a -> GenericLangM l m ())
-> Map k a -> Map k (GenericLangM l m ())
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map k a
m)

type OutputCapable m = GenericOutputCapable Language m

out :: Monad m => GenericOut l o -> GenericLangM l (GenericReportT l o m) ()
out :: forall (m :: * -> *) l o.
Monad m =>
GenericOut l o -> GenericLangM l (GenericReportT l o m) ()
out = GenericReportT l o m () -> GenericLangM l (GenericReportT l o m) ()
forall (f :: * -> *) a. Functor f => f a -> GenericLangM l f a
forall (t :: (* -> *) -> * -> *) (f :: * -> *) a.
(FunctorTrans t, Functor f) =>
f a -> t f a
lift (GenericReportT l o m ()
 -> GenericLangM l (GenericReportT l o m) ())
-> (GenericOut l o -> GenericReportT l o m ())
-> GenericOut l o
-> GenericLangM l (GenericReportT l o m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MaybeT (WriterT [GenericOut l o] m) () -> GenericReportT l o m ()
forall l o (m :: * -> *) r.
MaybeT (WriterT [GenericOut l o] m) r -> GenericReportT l o m r
Report (MaybeT (WriterT [GenericOut l o] m) () -> GenericReportT l o m ())
-> (GenericOut l o -> MaybeT (WriterT [GenericOut l o] m) ())
-> GenericOut l o
-> GenericReportT l o m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [GenericOut l o] -> MaybeT (WriterT [GenericOut l o] m) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell ([GenericOut l o] -> MaybeT (WriterT [GenericOut l o] m) ())
-> (GenericOut l o -> [GenericOut l o])
-> GenericOut l o
-> MaybeT (WriterT [GenericOut l o] m) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (GenericOut l o -> [GenericOut l o] -> [GenericOut l o]
forall a. a -> [a] -> [a]
:[])

instance (l ~ Language)
  => GenericOutputCapable l (GenericReportT l (IO ()) IO)
  where
  assertion :: Bool
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
assertion Bool
p GenericLangM l (GenericReportT l (IO ()) IO) ()
m = (if Bool
p then GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a. a -> a
id else GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
refuse)
    (GenericLangM l (GenericReportT l (IO ()) IO) ()
 -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a b. (a -> b) -> a -> b
$ Bool
-> LangM (GenericReportT l (IO ()) IO)
-> LangM (GenericReportT l (IO ()) IO)
forall (m :: * -> *). OutputCapable m => Bool -> LangM m -> LangM m
yesNo Bool
p GenericLangM l (GenericReportT l (IO ()) IO) ()
LangM (GenericReportT l (IO ()) IO)
m
  image :: String -> GenericLangM l (GenericReportT l (IO ()) IO) ()
image         = IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> (String -> IO ())
-> String
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO ()
putStr (String -> IO ()) -> (String -> String) -> String -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"file: " String -> String -> String
forall a. [a] -> [a] -> [a]
++)
  images :: forall k a.
(k -> String)
-> (a -> String)
-> Map k a
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
images k -> String
g a -> String
f    = IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> (Map k a -> IO ())
-> Map k a
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO ()
putStrLn (String -> IO ()) -> (Map k a -> String) -> Map k a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (k -> a -> String -> String) -> String -> Map k a -> String
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
foldrWithKey
    (\k
k a
x String
rs -> k -> String
g k
k String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
". file: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ a -> String
f a
x String -> String -> String
forall a. [a] -> [a] -> [a]
++ Char
'\n' Char -> String -> String
forall a. a -> [a] -> [a]
: String
rs)
    String
""
  paragraph :: GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
paragraph     = (GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a b.
GenericLangM l (GenericReportT l (IO ()) IO) a
-> GenericLangM l (GenericReportT l (IO ()) IO) b
-> GenericLangM l (GenericReportT l (IO ()) IO) b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (String -> IO ()
putStrLn String
""))
  text :: String -> GenericLangM l (GenericReportT l (IO ()) IO) ()
text          = IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> (String -> IO ())
-> String
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO ()
putStr
  enumerateM :: forall a.
(a -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> [(a, GenericLangM l (GenericReportT l (IO ()) IO) ())]
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
enumerateM a -> GenericLangM l (GenericReportT l (IO ()) IO) ()
p  = (GenericLangM l (GenericReportT l (IO ()) IO) ()
 -> (a, GenericLangM l (GenericReportT l (IO ()) IO) ())
 -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> [(a, GenericLangM l (GenericReportT l (IO ()) IO) ())]
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl
    (\GenericLangM l (GenericReportT l (IO ()) IO) ()
o (a
x, GenericLangM l (GenericReportT l (IO ()) IO) ()
e) -> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
paragraph (GenericLangM l (GenericReportT l (IO ()) IO) ()
 -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a b. (a -> b) -> a -> b
$ do GenericLangM l (GenericReportT l (IO ()) IO) ()
o; a -> GenericLangM l (GenericReportT l (IO ()) IO) ()
p a
x; IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStr String
"  "; GenericLangM l (GenericReportT l (IO ()) IO) ()
e; pure ())
    (() -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a. a -> GenericLangM l (GenericReportT l (IO ()) IO) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
  itemizeM :: [GenericLangM l (GenericReportT l (IO ()) IO) ()]
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
itemizeM      = (GenericLangM l (GenericReportT l (IO ()) IO) ()
 -> GenericLangM l (GenericReportT l (IO ()) IO) ()
 -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> [GenericLangM l (GenericReportT l (IO ()) IO) ()]
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl
    (\GenericLangM l (GenericReportT l (IO ()) IO) ()
o GenericLangM l (GenericReportT l (IO ()) IO) ()
x -> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
paragraph (GenericLangM l (GenericReportT l (IO ()) IO) ()
 -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a b. (a -> b) -> a -> b
$ do GenericLangM l (GenericReportT l (IO ()) IO) ()
o; IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStr String
" -  "; GenericLangM l (GenericReportT l (IO ()) IO) ()
x; pure ())
    (() -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a. a -> GenericLangM l (GenericReportT l (IO ()) IO) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ())
  indent :: GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
indent GenericLangM l (GenericReportT l (IO ()) IO) ()
xs     = do
    IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStr String
">>>>"
    GenericLangM l (GenericReportT l (IO ()) IO) ()
xs
    IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
"<<<<"
    pure ()
  refuse :: GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
refuse        = GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) l o.
Monad m =>
GenericLangM l (GenericReportT l o m) ()
-> GenericLangM l (GenericReportT l o m) ()
toAbort
  latex :: String -> GenericLangM l (GenericReportT l (IO ()) IO) ()
latex         = IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> (String -> IO ())
-> String
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO ()
putStrLn (String -> IO ()) -> (String -> String) -> String -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"LaTeX: " String -> String -> String
forall a. [a] -> [a] -> [a]
++)
  folded :: Bool
-> (l -> String)
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
folded Bool
b l -> String
t GenericLangM l (GenericReportT l (IO ()) IO) ()
c = do
    IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (if Bool
b then String
"+" else String
"-") String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") "
    (l -> String) -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
(l -> String) -> GenericLangM l m ()
translated l -> String
t
    IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStrLn String
""
    Bool
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
b (GenericLangM l (GenericReportT l (IO ()) IO) ()
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall l (m :: * -> *).
GenericOutputCapable l m =>
GenericLangM l m () -> GenericLangM l m ()
indent GenericLangM l (GenericReportT l (IO ()) IO) ()
c)
    pure ()
  code :: String -> GenericLangM l (GenericReportT l (IO ()) IO) ()
code          = IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) o l.
Monad m =>
o -> GenericLangM l (GenericReportT l o m) ()
format (IO () -> GenericLangM l (GenericReportT l (IO ()) IO) ())
-> (String -> IO ())
-> String
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO ()
putStr (String -> IO ()) -> (String -> String) -> String -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\String
xs -> String
" <" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
xs String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"> ")
  translatedCode :: (l -> String) -> GenericLangM l (GenericReportT l (IO ()) IO) ()
translatedCode l -> String
lm =
    GenericOut l (IO ())
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) l o.
Monad m =>
GenericOut l o -> GenericLangM l (GenericReportT l o m) ()
out ((l -> IO ()) -> GenericOut l (IO ())
forall l o. (l -> o) -> GenericOut l o
Localised ((l -> IO ()) -> GenericOut l (IO ()))
-> (l -> IO ()) -> GenericOut l (IO ())
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStr (String -> IO ()) -> (l -> String) -> l -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\String
xs -> String
" <" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
xs String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"> ") (String -> String) -> (l -> String) -> l -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. l -> String
lm)
  translated :: (l -> String) -> GenericLangM l (GenericReportT l (IO ()) IO) ()
translated l -> String
lm = GenericOut l (IO ())
-> GenericLangM l (GenericReportT l (IO ()) IO) ()
forall (m :: * -> *) l o.
Monad m =>
GenericOut l o -> GenericLangM l (GenericReportT l o m) ()
out ((l -> IO ()) -> GenericOut l (IO ())
forall l o. (l -> o) -> GenericOut l o
Localised ((l -> IO ()) -> GenericOut l (IO ()))
-> (l -> IO ()) -> GenericOut l (IO ())
forall a b. (a -> b) -> a -> b
$ String -> IO ()
putStr (String -> IO ()) -> (l -> String) -> l -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. l -> String
lm)

instance l ~ Language
  => RunnableOutputCapable l (GenericReportT l (IO ()) IO)
  where
  type RunMonad l (GenericReportT l (IO ()) IO) = IO
  type Output l (GenericReportT l (IO ()) IO) = IO ()
  runLangM :: forall a.
GenericLangM l (GenericReportT l (IO ()) IO) a
-> RunMonad
     l
     (GenericReportT l (IO ()) IO)
     (Maybe a, l -> Output l (GenericReportT l (IO ()) IO))
runLangM = IO ()
-> (IO () -> IO () -> IO ())
-> GenericLangM l (GenericReportT l (IO ()) IO) a
-> IO (Maybe a, l -> IO ())
forall (m :: * -> *) o l a.
Functor m =>
o
-> (o -> o -> o)
-> GenericLangM l (GenericReportT l o m) a
-> m (Maybe a, l -> o)
runLangMReport (() -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()) IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
(>>)

{-|
This is a more specific version of 'Generic.combineReports'
which enforces the usage pattern.
You should always prefer this version over the generic.
-}
combineReports
  :: Monad m
  => ([[o]] -> o)
  -> [GenericLangM l (GenericReportT l o m) ()]
  -> GenericLangM l (GenericReportT l o m) ()
combineReports :: forall (m :: * -> *) o l.
Monad m =>
([[o]] -> o)
-> [GenericLangM l (GenericReportT l o m) ()]
-> GenericLangM l (GenericReportT l o m) ()
combineReports = ([[o]] -> o)
-> [GenericLangM l (GenericReportT l o m) ()]
-> GenericLangM l (GenericReportT l o m) ()
forall (m :: * -> *) o l a.
Monad m =>
([[o]] -> o)
-> [GenericLangM l (GenericReportT l o m) a]
-> GenericLangM l (GenericReportT l o m) ()
Generic.combineReports

{-|
This is a more specific version of 'Generic.alignOutput'
which enforces the usage pattern.
You should always prefer this version over the generic.
-}
alignOutput
  :: Monad m
  => ([o] -> o)
  -> GenericLangM l (GenericReportT l o m) ()
  -> GenericLangM l (GenericReportT l o m) ()
alignOutput :: forall (m :: * -> *) o l.
Monad m =>
([o] -> o)
-> GenericLangM l (GenericReportT l o m) ()
-> GenericLangM l (GenericReportT l o m) ()
alignOutput = ([o] -> o)
-> GenericLangM l (GenericReportT l o m) ()
-> GenericLangM l (GenericReportT l o m) ()
forall (m :: * -> *) o l a.
Monad m =>
([o] -> o)
-> GenericLangM l (GenericReportT l o m) a
-> GenericLangM l (GenericReportT l o m) ()
Generic.alignOutput

{-|
This is a more specific version of 'Generic.combineTwoReports'
which enforces the usage pattern.
You should always prefer this version over the generic.
-}
combineTwoReports
  :: Monad m
  => ([o] -> [o] -> o)
  -> GenericLangM l (GenericReportT l o m) ()
  -> GenericLangM l (GenericReportT l o m) ()
  -> GenericLangM l (GenericReportT l o m) ()
combineTwoReports :: forall (m :: * -> *) o l.
Monad m =>
([o] -> [o] -> o)
-> GenericLangM l (GenericReportT l o m) ()
-> GenericLangM l (GenericReportT l o m) ()
-> GenericLangM l (GenericReportT l o m) ()
combineTwoReports = ([o] -> [o] -> o)
-> GenericLangM l (GenericReportT l o m) ()
-> GenericLangM l (GenericReportT l o m) ()
-> GenericLangM l (GenericReportT l o m) ()
forall (m :: * -> *) o l a b.
Monad m =>
([o] -> [o] -> o)
-> GenericLangM l (GenericReportT l o m) a
-> GenericLangM l (GenericReportT l o m) b
-> GenericLangM l (GenericReportT l o m) ()
Generic.combineTwoReports

{-|
This is a more specific version of 'Generic.toAbort'
which enforces the usage pattern.
You should always prefer this version over the generic.
-}
toAbort
  :: Monad m
  => GenericLangM l (GenericReportT l o m) ()
  -> GenericLangM l (GenericReportT l o m) ()
toAbort :: forall (m :: * -> *) l o.
Monad m =>
GenericLangM l (GenericReportT l o m) ()
-> GenericLangM l (GenericReportT l o m) ()
toAbort = GenericLangM l (GenericReportT l o m) ()
-> GenericLangM l (GenericReportT l o m) ()
forall (m :: * -> *) l o a b.
Monad m =>
GenericLangM l (GenericReportT l o m) a
-> GenericLangM l (GenericReportT l o m) b
Generic.toAbort