Help us understand the problem. What is going on with this article?

【解答例】Haskell アクションとラムダ 超入門

More than 5 years have passed since last update.

Haskell アクションとラムダ 超入門の解答例です。

シャッフル

【問1】次のコードからdoを取り除いて、>>=でつないでください。

import System.Random

shuffle [] = return []
shuffle xs =
    (getStdRandom $ randomR (0, length xs - 1) :: IO Int) >>= \n ->
    (shuffle $ take n xs ++ drop (n + 1) xs) >>= \xs' ->
    return $ (xs !! n) : xs'

main =
    shuffle [1..9] >>=
    print
実行結果(毎回異なる)
[3,5,4,9,2,7,8,6,1]

配列の更新

【問2】配列にはmodifyIORefに相当する関数がありません。modifyArrayを実装してください。

import Data.Array.IO
import Control.Applicative

modifyArray a i f = writeArray a i =<< f <$> readArray a i

main = do
    a <- newArray (0, 2) 0 :: IO (IOUArray Int Int)
    print =<< getElems a
    modifyArray a 1 (+ 5)
    print =<< getElems a
実行結果
[0,0,0]
[0,5,0]

再実装

【問3】replicateM, replicateM_, forM, forM_, when, unlessを再実装してください。関数名には'を付けてください。

import Control.Applicative
import System.Random

replicateM' 0 _ = return []
replicateM' n a | n > 0 = (:) <$> a <*> replicateM' (n - 1) a

replicateM_' 0 _ = return []
replicateM_' n a | n > 0 = a >> replicateM_' (n - 1) a

forM' [] _ = return []
forM' (x:xs) f = (:) <$> f x <*> forM' xs f

forM_' [] _ = return []
forM_' (x:xs) f = f x >> forM_' xs f

when' b a = if b then a else return ()
unless' b = when' $ not b

main = do
    let dice = getStdRandom $ randomR (1, 6) :: IO Int
    print =<< replicateM' 5 dice
    putStrLn "---"
    replicateM_' 3 $ do
        print =<< dice
    putStrLn "---"
    a <- forM' [1..3] $ \i -> do
        print i
        return i
    print a
    putStrLn "---"
    forM_' [1..3] $ \i -> do
        print i
    putStrLn "---"
    let y f = f (y f)
    y $ \f -> do
        r <- dice
        print r
        when' (r /= 1) f
    putStrLn "---"
    y $ \f -> do
        r <- dice
        print r
        unless' (r == 6) f
実行結果(毎回異なる)
[4,3,2,5,1]
---
2
6
2
---
1
2
3
[1,2,3]
---
1
2
3
---
3
2
1
---
6

正規乱数

【問4】0.0~1.0までのDouble型の乱数を12個足したものを四捨五入して6を引いた整数値について、100回の分布を求めてください。四捨五入にはroundではなく、切り捨て関数truncateを工夫して使用してください。

import Control.Monad
import System.Random

rand :: IO Double
rand = getStdRandom $ randomR (0.0, 1.0)

main = do
    r <- replicateM 100 $ do
        rands <- replicateM 12 rand
        return $ truncate (sum rands + 0.5) - 6
    forM_ [-3 .. 3] $ \i -> do
        let c = length $ filter (== i) r
            i' = show i
            n = replicate (2 - length i') ' ' ++ i'
        putStrLn $ n ++ ": " ++ replicate c '*'
実行結果(毎回異なる)
-3: *
-2: ******
-1: ****************************
 0: **********************************
 1: ***********************
 2: *******
 3: *

中心極限定理により正規乱数を生成しています。

7shi
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした