parent
9ed8fb2f6d
commit
a0ebfb83a3
7 changed files with 206 additions and 0 deletions
@ -0,0 +1,2 @@ |
||||
# Exercises: Roll Your Own |
||||
see src/RandomExample2.hs |
@ -0,0 +1,2 @@ |
||||
# Chapter Exercises |
||||
see src/chapter.hs |
@ -0,0 +1,26 @@ |
||||
{-# LANGUAGE InstanceSigs #-} |
||||
module Moi where |
||||
|
||||
newtype Moi s a = Moi { runMoi :: s -> (a, s) } |
||||
|
||||
instance Functor (Moi s) where |
||||
fmap :: (a -> b) -> Moi s a -> Moi s b |
||||
fmap f (Moi g) = Moi $ \s -> let (a, s') = g s |
||||
in (f a, s') |
||||
|
||||
instance Applicative (Moi s) where |
||||
pure :: a -> Moi s a |
||||
pure a = Moi $ \s -> (a, s) |
||||
|
||||
(<*>) :: Moi s (a -> b) -> Moi s a -> Moi s b |
||||
(Moi f) <*> (Moi g) = Moi $ \s -> let (a, s') = g s |
||||
(f', s'') = f s' |
||||
in (f' a, s'') |
||||
|
||||
instance Monad (Moi s) where |
||||
return :: a -> Moi s a |
||||
return = pure |
||||
|
||||
(>>=) :: Moi s a -> (a -> Moi s b) -> Moi s b |
||||
(Moi f) >>= g = Moi $ \s -> let (a, s') = f s |
||||
in runMoi (g a) s' |
@ -0,0 +1,32 @@ |
||||
module RandomExample where |
||||
|
||||
import System.Random |
||||
|
||||
-- Six-sided die |
||||
data Die = |
||||
DieOne |
||||
| DieTwo |
||||
| DieThree |
||||
| DieFour |
||||
| DieFive |
||||
| DieSix |
||||
deriving (Eq, Show) |
||||
|
||||
intToDie :: Int -> Die |
||||
intToDie n = case n of |
||||
1 -> DieOne |
||||
2 -> DieTwo |
||||
3 -> DieThree |
||||
4 -> DieFour |
||||
5 -> DieFive |
||||
6 -> DieSix |
||||
-- Use 'error' _extremely_ sparingly |
||||
x -> error $ "intToDie got non 1-6 integer: " ++ show x |
||||
|
||||
rollDieThreeTimes :: (Die, Die, Die) |
||||
rollDieThreeTimes = do |
||||
let s = mkStdGen 0 |
||||
(d1, s1) = randomR (1, 6) s |
||||
(d2, s2) = randomR (1, 6) s1 |
||||
(d3, _) = randomR (1, 6) s2 |
||||
(intToDie d1, intToDie d2, intToDie d3) |
@ -0,0 +1,57 @@ |
||||
module RandomExample2 where |
||||
|
||||
import Control.Applicative (liftA3) |
||||
import Control.Monad (replicateM) |
||||
import Control.Monad.Trans.State |
||||
import System.Random |
||||
import RandomExample |
||||
|
||||
|
||||
rollDie :: State StdGen Die |
||||
rollDie = state $ do |
||||
(n, s) <- randomR (1, 6) |
||||
return (intToDie n, s) |
||||
|
||||
rollDie' :: State StdGen Die |
||||
rollDie' = intToDie <$> state (randomR (1, 6)) |
||||
|
||||
rollDieThreeTimes' :: State StdGen (Die, Die, Die) |
||||
rollDieThreeTimes' = liftA3 (,,) rollDie' rollDie' rollDie' |
||||
|
||||
infiniteDie :: State StdGen [Die] |
||||
infiniteDie = repeat <$> rollDie' |
||||
|
||||
nDie :: Int -> State StdGen [Die] |
||||
nDie n = replicateM n rollDie |
||||
|
||||
rollsToGetTwenty :: StdGen -> Int |
||||
rollsToGetTwenty g = go 0 0 g |
||||
where go :: Int -> Int -> StdGen -> Int |
||||
go sum' count gen |
||||
| sum' >= 20 = count |
||||
| otherwise = let (die, nextGen) = randomR (1, 6) gen |
||||
in go (sum' + die) (count + 1) nextGen |
||||
|
||||
-- Exercises: Roll Your Own |
||||
-- 1 |
||||
rollsToGetN :: Int -> StdGen -> Int |
||||
rollsToGetN n g = go 0 0 g |
||||
where go :: Int -> Int -> StdGen -> Int |
||||
go sum' count gen |
||||
| sum' >= n = count |
||||
| otherwise = let (die, nextGen) = randomR (1, 6) gen |
||||
in go (sum' + die) (count + 1) nextGen |
||||
|
||||
-- 2 |
||||
rollsCountLogged :: Int -> StdGen -> (Int, [Die]) |
||||
rollsCountLogged n g = go 0 (0, []) g |
||||
where go :: Int -> (Int, [Die]) -> StdGen -> (Int, [Die]) |
||||
go sum' r@(count, dice) gen |
||||
| sum' >= n = r |
||||
| otherwise = let (die, nextGen) = randomR (1, 6) gen |
||||
in go (sum' + die) |
||||
((count + 1), intToDie die : dice) |
||||
nextGen |
||||
|
||||
rollsToGetN' :: Int -> StdGen -> Int |
||||
rollsToGetN' n = fst . rollsCountLogged n |
@ -0,0 +1,35 @@ |
||||
module Chapter where |
||||
|
||||
newtype State s a = State { runState :: s -> (a, s) } |
||||
instance Functor (State s) where |
||||
fmap f k = State $ \s -> let (a, s') = runState k s |
||||
in (f a, s') |
||||
instance Applicative (State s) where |
||||
pure a = State $ \s -> (a, s) |
||||
(State f) <*> k = State $ \s -> let (a, s') = runState k s |
||||
(f', s'') = f s' |
||||
in (f' a, s'') |
||||
instance Monad (State s) where |
||||
return = pure |
||||
(State f) >>= k = State $ \s -> let (a, s') = f s |
||||
in runState (k a) s' |
||||
|
||||
-- 1 |
||||
get :: State s s |
||||
get = State $ \s -> (s,s) |
||||
|
||||
-- 2 |
||||
put :: s -> State s () |
||||
put s = State $ \_ -> ((),s) |
||||
|
||||
-- 3 |
||||
exec :: State s a -> s -> s |
||||
exec st = snd . runState st |
||||
|
||||
-- 4 |
||||
eval :: State s a -> s -> a |
||||
eval st = fst . runState st |
||||
|
||||
-- 5 |
||||
modify :: (s -> s) -> State s () |
||||
modify f = State $ \s -> ((), f s) |
@ -0,0 +1,52 @@ |
||||
module FizzBuzz where |
||||
|
||||
import Control.Monad |
||||
import Control.Monad.Trans.State |
||||
-- http://hackage.haskell.org/package/dlist |
||||
-- import qualified Data.DList as DL |
||||
|
||||
fizzBuzz :: Integer -> String |
||||
fizzBuzz n | n `mod` 15 == 0 = "FizzBuzz" |
||||
| n `mod` 5 == 0 = "Buzz" |
||||
| n `mod` 3 == 0 = "Fizz" |
||||
| otherwise = show n |
||||
|
||||
-- fizzbuzzlist :: [Integer] -> DL.DList String |
||||
-- fizzbuzzlist list = execState (mapM_ addResult list) DL.empty |
||||
|
||||
-- addResult :: Integer -> State (DL.DList String) () |
||||
-- addResult n = do |
||||
-- xs <- get |
||||
-- let result = fizzBuzz n |
||||
-- put (DL.snoc xs result) |
||||
|
||||
-- main :: IO () |
||||
-- main = mapM_ putStrLn $ fizzbuzzlist [1..100] |
||||
|
||||
fizzbuzzlist :: [Integer] -> [String] |
||||
fizzbuzzlist list = execState (mapM_ addResult list) [] |
||||
|
||||
addResult :: Integer -> State [String] () |
||||
addResult n = do |
||||
xs <- get |
||||
let result = fizzBuzz n |
||||
put (result : xs) |
||||
|
||||
-- they all seem to take about the same amount of time... |
||||
main :: IO () |
||||
-- main = mapM_ putStrLn $ reverse $ fizzbuzzlist [1..100] |
||||
main = mapM_ putStrLn $ fizzbuzzFromTo 1 500000 |
||||
-- main = mapM_ putStrLn $ fizzbuzzFromTo' 1 500000 |
||||
|
||||
fizzbuzzFromTo :: Integer -> Integer -> [String] |
||||
fizzbuzzFromTo from to = go from to [] |
||||
where go f t st |
||||
| f >= t = st |
||||
| otherwise = execState (addResult f) (go (f+1) t st) |
||||
|
||||
fizzbuzzFromTo' :: Integer -> Integer -> [String] |
||||
fizzbuzzFromTo' from to = execState (mapM_ addResult list) [] |
||||
where list = go from to [] |
||||
go f t l |
||||
| f >= t = l |
||||
| otherwise = go (f+1) t (f:l) |
Loading…
Reference in new issue