fork(2) download
  1. module Main where
  2.  
  3. --
  4. -- In order to use "do" notation, we need to declare instances
  5. -- of the Monad typeclass. In order to do that we must jump through
  6. -- some hoops:
  7. -- * We need a name for the datatype we are using (hence the new "Counter" type)
  8. -- * We also must declare instances of Functor and Applicative
  9. -- (this is something that changed in Haskell 7.10.
  10. -- See https://w...content-available-to-author-only...l.org/Functor-Applicative-Monad_Proposal )
  11. -- (Applicative's "pure" is the same as Monad's "return")
  12. --
  13.  
  14. -- Integer arithmetic with (+) and (/)
  15. data Term =
  16. N Int
  17. | Plus Term Term
  18. | Div Term Term
  19.  
  20. --
  21. -- Basic evaluator
  22. --
  23.  
  24. eval :: Term -> Int
  25. eval (N n) = n
  26. eval (Plus t1 t2) = eval t1 + eval t2
  27. eval (Div t1 t2) = eval t1 `div` eval t2
  28.  
  29. --
  30. -- Evaluator that counts the number of operations
  31. --
  32.  
  33. newtype Counter a = Counter (Int -> (Int, a))
  34.  
  35. unCounter :: Counter a -> (Int -> (Int, a))
  36. unCounter (Counter f) = f
  37.  
  38. instance Functor Counter where
  39. -- fmap :: (a -> b) -> Counter a -> Counter b
  40.  
  41. instance Applicative Counter where
  42. -- pure :: a -> Counter a
  43. pure n = undefined
  44.  
  45. -- Counter (a -> b) -> Counter a -> Counter b
  46. c1 <*> c2 = undefined
  47.  
  48. instance Monad Counter where
  49. -- (>>=) :: Counter a -> (a -> Counter b) -> Counter b
  50. m >>= f = undefined
  51.  
  52. runC :: Counter a -> Int -> (Int, a)
  53. runC s0 c = undefined
  54.  
  55. inc :: Counter ()
  56. inc = undefined
  57.  
  58. evalWithCount :: Term -> (Int, Int)
  59. evalWithCount t = runC (eval' t) 0
  60. where
  61. eval' :: Term -> Counter Int
  62. eval' (N n) =
  63. return n
  64. eval' (Plus t1 t2) = do
  65. n1 <- eval' t1
  66. n2 <- eval' t2
  67. inc
  68. return (n1 + n2)
  69. eval' (Div t1 t2) = do
  70. n1 <- eval' t1
  71. n2 <- eval' t2
  72. inc
  73. return (n1 `div` n2)
  74.  
  75. --
  76. -- Evaluator that catches division by zero
  77. --
  78. -- Returns (Ok n) in case of success
  79. -- Returns (Error "Division by zero") otherwise
  80. --
  81.  
  82.  
  83. data Result a = Error String | Ok a deriving Show
  84.  
  85. instance Functor Result where
  86. -- fmap :: (a -> b) -> Result a -> Result b
  87. fmap f r = undefined
  88.  
  89. instance Applicative Result where
  90. -- pure :: a -> Result a
  91. pure n = undefined
  92.  
  93. r1 <*> r2 = undefined
  94.  
  95. instance Monad Result where
  96. -- (>>=) :: Result a -> (a -> Result a) -> Result b
  97. m >>= f = undefined
  98.  
  99. throw :: String -> Result a
  100. throw s = undefined
  101.  
  102. evalChecked :: Term -> Result Int
  103. evalChecked (N n) =
  104. return n
  105. evalChecked (Plus t1 t2) = do
  106. n1 <- evalChecked t1
  107. n2 <- evalChecked t2
  108. return (n1 + n2)
  109. evalChecked (Div t1 t2) = do
  110. n1 <- evalChecked t1
  111. n2 <- evalChecked t2
  112. if n2 == 0 then
  113. throw "Division by zero"
  114. else
  115. return (n1 `div` n2)
  116.  
  117. main = print (undefined::String)
  118.  
Runtime error #stdin #stdout #stderr 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
prog: Prelude.undefined
CallStack (from HasCallStack):
  error, called at libraries/base/GHC/Err.hs:79:14 in base:GHC.Err
  undefined, called at prog.hs:118:15 in main:Main