Repository navigation
Expand file tree
/
Copy pathMain.hs
More file actions
97 lines (78 loc) · 3.03 KB
/
Copy pathMain.hs
File metadata and controls
97 lines (78 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedLabels #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Main (main) where
import Control.Applicative (empty)
import Data.Text (Text)
import Options.Applicative (Parser, auto, execParser, info, str)
import Toml (TomlCodec, (.=))
import Trial ((::-), Phase (..), Trial (..), fiasco, prettyTrial, withTag)
import Trial.OptparseApplicative (taggedTrialOption)
import Trial.Tomland (taggedTrialMaybeCodec, taggedTrialStrCodec)
import qualified Data.Text.IO as TIO
import qualified Toml
main :: IO ()
main = parseOptions >>= TIO.putStrLn . prettyTrial
{-
https://medium.com/@jonathangfischoff/the-partial-options-monoid-pattern-31914a71fc67
-}
data OptionsP (p :: Phase Text) = OptionsP
{ oRetryCount :: !(p ::- Int)
, oHost :: !(p ::- Text)
, oCharacterCode :: !(p ::- Maybe Bool)
}
deriving stock instance
( Show (p ::- Text)
, Show (p ::- Int)
, Show (p ::- Maybe Bool)
) => Show (OptionsP p)
-- | Incomplete options with 'TaggedTrial'.
type PartialOptions = OptionsP 'Partial
-- | Complete options.
type Options = OptionsP 'Final
instance Semigroup PartialOptions where
x <> y = OptionsP
{ oRetryCount = oRetryCount x <> oRetryCount y
, oHost = oHost x <> oHost y
, oCharacterCode = oCharacterCode x <> oCharacterCode y
}
finaliseOptions :: PartialOptions -> Trial Text Options
finaliseOptions opts = do
oRetryCount <- #oRetryCount opts
oHost <- #oHost opts
oCharacterCode <- #oCharacterCode opts
pure OptionsP {..}
defaultPartialOptions :: PartialOptions
defaultPartialOptions = OptionsP
{ oRetryCount = withTag "Default" $ pure 5
, oHost = withTag "Default" $ fiasco "No default value for Host"
, oCharacterCode = withTag "Default" empty
}
partialOptionsParser :: Parser PartialOptions
partialOptionsParser = OptionsP
<$> taggedTrialOption "retry-count" auto
<*> taggedTrialOption "host" str
<*> taggedTrialOption "character-code" auto
-- TOML
partialOptionsCodec :: TomlCodec PartialOptions
partialOptionsCodec = OptionsP
<$> taggedTrialStrCodec Toml.int "retry-count" .= oRetryCount
<*> taggedTrialStrCodec Toml.text "host" .= oHost
<*> taggedTrialMaybeCodec (Toml.bool "character-code") .= oCharacterCode
parseOptions :: IO (Trial Text Options)
parseOptions = do
cmdLineOptions <- execParser $ info partialOptionsParser mempty
toml <- Toml.decodeFileEither partialOptionsCodec "trial-example/options.toml"
let tomlOptions = case toml of
Left errs -> let e = fiasco $ Toml.prettyTomlDecodeErrors errs in
OptionsP e e e
Right a -> a
let combinedOptions =
defaultPartialOptions
<> cmdLineOptions
<> tomlOptions
pure $ finaliseOptions combinedOptions