Última actividad 1746901694

Revisión e820f0e5753d5a1b1ca6b7cebb6d02b9d53553b2

ArithCmdDo.idr Sin formato Playground
1module ArithCmdDo
2import Data.String
3import Data.Primitives.Views
4import Data.Bits
5import System
6import System.File
7%default total
8
9data Input = Answer Int
10 | QuitCmd
11
12data Command : Type -> Type where
13 PutStr : String -> Command ()
14 GetLine : Command String
15 ReadFile : String -> Command (Either FileError String)
16 WriteFile : String -> String -> Command (Either FileError Unit)
17
18 Pure : ty -> Command ty
19 Bind : Command a -> (a -> Command b) -> Command b
20 Next : Command () -> Command b -> Command b
21
22data ConsoleIO : Type -> Type where
23 Quit : a -> ConsoleIO a
24 Do : Command a -> (a -> Inf (ConsoleIO b)) -> ConsoleIO b
25 Seq : Command () -> Inf (ConsoleIO b) -> ConsoleIO b
26
27namespace CommandDo
28 export
29 (>>=) : Command a -> (a -> Command b) -> Command b
30 (>>=) = Bind
31
32 export
33 (>>) : Command () -> Command b -> Command b
34 (>>) = Next
35
36namespace ConsoleDo
37 export
38 (>>=) : Command a -> (a -> Inf (ConsoleIO b)) -> ConsoleIO b
39 (>>=) = Do
40
41 export
42 (>>) : Command () -> Inf (ConsoleIO b) -> ConsoleIO b
43 (>>) = Seq
44
45totalReadLine : HasIO io => (file : String) -> io (Either FileError String)
46totalReadLine fileName
47 = do Right file <- openFile fileName Read
48 | Left e => pure (Left e)
49 Right size <- fileSize file
50 | Left e => do closeFile file
51 pure (Left e)
52 Right result <- fGetChars file size
53 | Left e => do closeFile file
54 pure (Left e)
55 pure (Right result)
56
57
58runCommand : Command a -> IO a
59runCommand (PutStr str)
60 = putStr str
61runCommand GetLine
62 = getLine
63runCommand (ReadFile file)
64 = totalReadLine file
65runCommand (WriteFile file contents)
66 = writeFile file contents
67runCommand (Pure val)
68 = pure val
69runCommand (Bind c f)
70 = do res <- runCommand c
71 runCommand (f res)
72runCommand (Next c f)
73 = do res <- runCommand c
74 runCommand f
75
76
77readInput : (prompt : String) -> Command Input
78readInput prompt = do PutStr prompt
79 answer <- GetLine
80 case (toLower answer == "quit") of
81 True => Pure QuitCmd
82 False => Pure (Answer (cast answer))
83
84
85
86run : Fuel -> ConsoleIO a -> IO (Maybe a)
87run Dry _ = pure Nothing
88run (More fuel) (Quit result) = pure (Just result)
89run (More fuel) (Do c f) = do res <- runCommand c; run fuel (f res)
90run (More fuel) (Seq c f) = do runCommand c; run fuel f
91
92
93mutual
94 correct : (nums : Stream Int) -> (score : Nat) -> (count : Nat) -> ConsoleIO (Nat, Nat)
95 correct nums score count
96 = do PutStr "Correct!\n"
97 quiz nums (score + 1) (count + 1)
98
99 wrong : (nums : Stream Int) -> (ans : Int) -> (score : Nat) -> (count : Nat) -> ConsoleIO (Nat, Nat)
100 wrong nums ans score count
101 = do PutStr ("Wrong, the anwser is " ++ show ans ++ "\n")
102 quiz nums score (count + 1)
103
104 quiz : Stream Int -> (score : Nat) -> (count : Nat) -> ConsoleIO (Nat, Nat)
105 quiz (num1 :: num2 :: nums) score count
106 = do PutStr ("Score so far: " ++ show score ++ " / " ++ show count ++ "\n")
107 input <- readInput (show num1 ++ " * " ++ show num2 ++ "? ")
108 case input of
109 Answer answer => if answer == num1 * num2
110 then correct nums score count
111 else wrong nums (num1 * num2) score count
112 QuitCmd => Quit (score, count)
113
114randoms : Int -> Stream Int
115randoms seed =
116 let
117 seed' = 1664525 * seed + 1013904223
118 in
119 (seed' `shiftR` 2) :: randoms seed'
120
121
122arithInputs : Int -> Stream Int
123arithInputs seed = map bound (randoms seed)
124 where
125 bound : Int -> Int
126 bound num with (divides num 12)
127 bound ((12 * div) + rem) | (DivBy div rem prf) = rem + 1
128
129partial
130main1 : IO ()
131main1 = do seed <- time
132 Just (score, count) <- run forever (quiz (arithInputs (fromInteger seed)) 0 0)
133 | Nothing => putStrLn "Ran out of fuel"
134 putStrLn ("Final score: " ++ show score ++ " / " ++ show count)