SlideShare a Scribd company logo
1 of 37
Download to read offline
オープンクラウド・キャンパス

第14章
もうちょっとだけモナド

中井悦司
Twitter @enakai00
14.1 Writer? 中の人なんていません!
第14章 もうちょっとだけモナド

ログを追記していく演算
 やりたいことのイメージ
現在値
・・・
・・・

3
×2

・・・
・・・
2倍した

6

ログファイル

 ちょっと一般化
現在値
・・・
・・・

x

f x = (y, newLog)

・・・
・・・
newLog

y

applyLog :: (a, String) -> (a -> (b, String)) -> (b, String)
applyLog (x, log) f = let (y, newLog) = f x
in (y, log ++ newLog)
3

Open Cloud Campus
第14章 もうちょっとだけモナド

ログを追記していく演算
 簡単な例
$ cat hoge.hs
applyLog :: (a, String) -> (a -> (b, String)) -> (b, String)
applyLog (x, log) f = let (y, newLog) = f x
in (y, log ++ newLog)
isBigGang :: Int -> (Bool, String)
isBigGang x = (x > 9, "Compared gang size to 9.")
$ ghci hoge.hs
*Main> (3, "Smallish gang.") `applyLog` isBigGang
(False,"Smallish gang.Compared gang size to 9.")
*Main> (30, "A freaking platoon.") `applyLog` isBigGang
(True,"A freaking platoon.Compared gang size to 9.")
*Main> ("Tobin", "Got outloaw name.") `applyLog` (x -> (length x, "Applied length."))
(5,"Got outloaw name.Applied length.")

4

Open Cloud Campus
第14章 もうちょっとだけモナド

ログ(String)を一般のモノイドに置き換える
 ログの本質は追加していけることです。
– そこで、追加操作をモノイドのmappendに置き換えてみます。
applyLog :: (Monoid m) => (a, m) -> (a -> (b, m)) -> (b, m)
applyLog (x, log) f = let (y, newLog) = f x
in (y, log `mappend` newLog)
– モノイドの定義とモノイド則
class Monoid a where
mempty :: a
mappend :: a -> a -> a
結合則 (a mappend b) mappend c == a mappend (b mappend c)
単位元 mempty mappend a == a mappend mempty == a

– モノイドの例
instance Monoid [a] where
mempty = []
mappend = (++)
※Monoidの類は「*」なので具体型が必要

5

Data.Monoidで定義
newtype Sum a = Sum { getSum :: a }
deriving (Eq, Ord, Read, Show, Bounded)
instance Num a => Monoid (Sum a) where
mempty = Sum 0
Sum x `mappend` Sum y = Sum (x + y)
Open Cloud Campus
第14章 もうちょっとだけモナド

ログ(String)を一般のモノイドに置き換える
 モノイドの例としてSum Intを取って、合計価格をログとして利用してみます。
$ cat hoge.hs
import Data.Monoid
applyLog :: (Monoid m) => (a, m) -> (a -> (b, m)) -> (b, m)
applyLog (x, log) f = let (y, newLog) = f x
in (y, log `mappend` newLog)
type Food = String
type Price = Sum Int
-- Add appropriate drink for a given food.
addDrink :: Food -> (Food, Price)
addDrink "beans" = ("milk", Sum 25)
addDrink "jerky" = ("whiskey", Sum 99)
addDrink _ = ("beer", Sum 30)
$ ghci hoge.hs
*Main> ("beans", Sum 10) `applyLog` addDrink
("milk",Sum {getSum = 35})
*Main> ("jerky", Sum 25) `applyLog` addDrink
("whiskey",Sum {getSum = 124})
6

Open Cloud Campus
第14章 もうちょっとだけモナド

applyLogをバインド演算に置き換える
 「値」と「ログ(モナド)」の組を一般の型aとwに置き換えたものをWriter型と
して定義します。
newtype Writer w a = Writer { runWriter :: (a, w) }

 applyLogがバインド演算になるようにWriterモナドを定義します。
※Monadの類は「*->*」なので型パラメータ「a」は含めない

instance (Monoid w) => Monad (Writer w) where
return x = Writer (x, mempty)
(Writer (x, v)) >>= f = let (Writer (y, v')) = f x
in Writer (y, v `mappend` v')

applyLog :: (Monoid m) => (a, m) -> (a -> (b, m)) -> (b, m)
applyLog (x, log) f = let (y, newLog) = f x
in (y, log `mappend` newLog)

7

Open Cloud Campus
第14章 もうちょっとだけモナド

applyLogをバインド演算に置き換える
 Monad則の証明
・左恒等性
retrun x >>= f
<=> Writer (x, empty) >>= f
<=> let (Writer (y, v')) = f x in Writer (y, mempty `mappend` v')
<=> let (Writer (y, v')) = f x in Writer (y, v')
<=> f x
・右恒等性
一般にWriter型の値mに対して、m = Writer (m_x, m_v)で、m_xとm_vを定義する。(m_x := fst (runWriter m), m_v := snd (runWriter m))
m >>= return
<=> let (Writer (y, v')) = return m_x in Writer (y, m_v `mappend` v')
<=> let (Writer (y, v')) = Writer (m_x, mempty) in Writer (y, m_v `mappend` v')
<=> Writer (m_x, m_v `mappend` mempty)
<=> Writer (m_x, m_v)
<=> m
・結合則
(m >>= f) <=> Writer ( (f m_x)_x, m_v `mappend` (f m_x)_v )
よって、結合則の左辺は
(m >>= f) >>= g <=> Writer ( (g (f m_x)_x)_x, (m_v `mappend` (f m_x)_v) `mappend` (g (f m_x)_x)_v ) ---(1)
一方、結合則の右辺は
m >>= (x -> f x >>= g) <=> Writer ( ((f m_x) >>= g)_x, m_v `mappend` ((f m_x) >>= g)_v ) ----(2)
ここで
f m_x >>= g <=> Writer ( (g (f m_x)_x)_x, (f m_x)_v `mappend` (g (f m_x)_x)_v)
よって、
(2) <=> Writer ((g (f m_x)_x)_x, m_v `mappend` ((f m_x)_v `mappend` (g (f m_x)_x)_v)) ) ---(3)
(1)と(3)で、mappendの結合則より、(1) <=> (3)

8

Open Cloud Campus
第14章 もうちょっとだけモナド

ログ(String)を一般のモノイドに置き換える
 addDrinkの例をWriterモナドで書きなおしてみます。
$ cat hoge.hs
import Data.Monoid
newtype Writer w a = Writer { runWriter :: (a, w) }
instance (Monoid w) => Monad (Writer w) where
return x = Writer (x, mempty)
(Writer (x, v)) >>= f = let (Writer (y, v')) = f x
in Writer (y, v `mappend` v')
type Food = String
type Price = Sum Int
-- Add appropriate drink for a given food.
addDrink :: Food -> Writer Price Food
addDrink "beans" = Writer ("milk", Sum 25)
addDrink "jerky" = Writer ("whiskey", Sum 99)
addDrink _ = Writer ("beer", Sum 30)
$ ghci hoge.hs
*Main> runWriter $ Writer ("beans", Sum 10) >>= addDrink
("milk",Sum {getSum = 35})
*Main> runWriter $ Writer ("jerky", Sum 25) >>= addDrink
("whiskey",Sum {getSum = 124})
9

Open Cloud Campus
第14章 もうちょっとだけモナド

do記法によるWriterモナドの使用例
 Writerモナドは、Control.Monad.Writerで定義されています。
– 値コンストラクタが「writer」(頭が小文字)なので注意。
$ cat hoge.hs
import Control.Monad.Writer
logNumber :: Int -> Writer [String] Int
logNumber x = writer (x, ["Got number: " ++ show x])
threeWithLog :: Writer [String] Int
threeWithLog = do
a <- logNumber 3
return a
{threeWithLog = (logNumber 3) >>= (a -> return a)
-}

$ ghci hoge.hs
*Main> runWriter threeWithLog
(3,["Got number: 3"])
*Main> runWriter multWithLog
(15,["Got number: 3","Got number: 5"])

multWithLog :: Writer [String] Int
multWithLog = do
a <- logNumber 3
b <- logNumber 5
return (a*b)
{multWithLog = (logNumber 3) >>= a ->
(logNumber 5) >>= b -> return (a*b)
-}

10

Open Cloud Campus
第14章 もうちょっとだけモナド

do記法によるWriterモナドの使用例
 do記法の中に、変数に束縛しないWriter型の値を入れるとログの追記のみが行わ
れます。
$ cat hoge.hs
import Control.Monad.Writer
logNumber :: Int -> Writer [String] Int
logNumber x = writer (x, ["Got number: " ++ show x])
threeWithLog :: Writer [String] Int
threeWithLog = do
a <- logNumber 3
writer ((), ["Hello, World!"])
return a
{threeWithLog = (logNumber 3) >>= a ->
writer ((), ["Hello, World!"]) >>= _ -> return a
-}
※この値は捨てられるので、何でもよい。
$ ghci hoge.hs
*Main> runWriter threeWithLog'
(3,["Got number: 3","Hello, World"])

11

Open Cloud Campus
第14章 もうちょっとだけモナド

do記法によるWriterモナドの使用例
 同じことをする関数tellが用意されています。
$ cat hoge.hs
import Control.Monad.Writer
logNumber :: Int -> Writer [String] Int
logNumber x = writer (x, ["Got number: " ++ show x])
multWithLog :: Writer [String] Int
multWithLog = do
a <- logNumber 3
b <- logNumber 5
tell ["Gonna multiply these two"]
return (a*b)
$ ghci hoge.hs
*Main> runWriter multWithLog
(15,["Got number: 3","Got number: 5","Gonna multiply these two"])

 tellの定義はこんな感じ(のはず)。
tell :: (Monoid a) => a -> Writer a ()
tell log = writer ((), log)
12

Open Cloud Campus
第14章 もうちょっとだけモナド

再帰処理のログを取得する
 ユークリッドの互除法
$ cat hoge.hs
import Control.Monad.Writer
mygcd :: Int -> Int -> Int
mygcd a b
| b == 0
= a
| otherwise = mygcd b (a `mod` b)
gcdWithLog :: Int -> Int -> Writer [String] Int
gcdWithLog a b
| b == 0
= do
tell ["Finished with " ++ show a]
return a
| otherwise = do
tell [show a ++ " mod " ++ show b ++ " = " ++ show (a `mod` b)]
gcdWithLog b (a `mod` b)
$ ghci hoge.hs
*Main> mygcd 8 3
1
*Main> runWriter $ gcdWithLog 8 3
(1,["8 mod 3 = 2","3 mod 2 = 1","2 mod 1 = 0","Finished with 1"])
*Main> mapM_ putStrLn $ snd $ runWriter $ gcdWithLog 8 3
8 mod 3 = 2
3 mod 2 = 1
2 mod 1 = 0
Finished with 1

13

Open Cloud Campus
第14章 もうちょっとだけモナド

リストの結合順序を考える
 「gcdWithLog 3 2」を運算すると、リストは右結合で展開されるので効率的。
gcdWithLog 3 2
<=> tell ["3 mod 2 = 1"] >>= _ -> gcdWithLog 2 1 ---- (1)
ここで
gcdWithLog 2 1
<=> tell ["2 mod 1
<=> tell ["2 mod 1
<=> tell ["2 mod 1
<=> writer (1, ["2

= 0"]
= 0"]
= 0"]
mod 1

>>= _ -> gcdWithLog 1 0
>>= _ -> (tell ["Finished with 1"] >>= _ -> return 1)
>>= _ -> writer (1, ["Finished with 1"] ++ [])
= 0"] ++ (["finished with 1"] ++ []))

よって
(1) <=> tell ["3 mod 2 = 1"] >>= _ -> writer (1, ["2 mod 1 = 0"] ++ (["finished with 1"] ++ []))
<=> writer (1, ["3 mod 2 = 1"] ++ (["2 mod 1 = 0"] ++ (["finished with 1"] ++ [])))

※リストの右結合と左結合の効率の違い
data [a] = [] | a : [a] deriving (Eq, Ord)
(++) :: [a] -> [a] -> [a]
(++) xs ys = foldr (:) ys xs
右結合 x ++ ys <=> x : xs == O(1)
左結合 xs ++ y <=> foldr (:) xs y == O(n)

14

Open Cloud Campus
第14章 もうちょっとだけモナド

リストの結合順序を考える
 一方、計算経過を逆順にログに記録するgcdReverseは、リストが左結合で展開さ
れるので非効率的
$ cat hoge.hs
import Control.Monad.Writer
gcdReverse :: Int -> Int -> Writer [String] Int
gcdReverse a b
| b == 0
= do
tell ["Finished with " ++ show a]
return a
| otherwise = do
result <- gcdReverse b (a `mod` b)
tell [show a ++ " mod " ++ show b ++ " = " ++ show (a `mod` b)]
return result
$ ghci hoge.hs
*Main> runWriter $ gcdReverse 3 2
(1,["Finished with 1","2 mod 1 = 0","3 mod 2 = 1"])
gcdReverse 3 2
<=> gcdReverse 2 1 >>= result -> (tell ["3 mod 2 = 1"] >>= (_ -> return result))
<=> gcdReverse 2 1 >>= result -> writer (result, ["3 mod 2 = 1"] ++ []) ---- (1)
ここで
gcdReverse 2 1
<=> gcdReverse 1 0 >>= result -> (tell ["2 mod 1 = 0"] >>= (_ -> return result))
<=> (tell ["Finished with 1"] >>= _ -> return 1) >>= result -> (tell ["2 mod 1 = 0"] >>= (_ -> return result))
<=> writer (1, ["Finished with 1"] ++ []) >>= result -> writer (result, ["2 mod 1 = 0"] ++ [])
<=> writer (1, (["Finished with 1"] ++ []) ++ (["2 mod 1 = 0"] ++ []))

15

よって
(1) <=> writer (1, (["Finished with 1"] ++ []) ++ (["2 mod 1 = 0"] ++ [])) >>= result -> writer (result, ["3 mod 2 = 1"] ++ [])
<=> writer (1, (["Finished with 1"] ++ []) ++ (["2 mod 1 = 0"] ++ []) ++ (["3 mod 2 = 1"] ++ []))
Open Cloud Campus
第14章 もうちょっとだけモナド

リストの結合を効率的に扱うテクニック
 次のDiffList(差分リスト)を使うと、リストの結合処理を効率化できます。
– 結合の評価を任意のタイミングまで遅延させて、最後に右結合で評価させます。
newtype DiffList a = DiffList { getDiffList :: [a] -> [a] }
toDiffList :: [a] -> DiffList a
toDiffList ys = DiffList (xs -> ys ++ xs)
fromDiffList :: DiffList a -> [a]
fromDiffList (DiffList f) = f []
instance Monoid (DiffList a) where
mempty = DiffList (xs -> [] ++ xs)
(DiffList f) `mappend` (DiffList g) = DiffList (xs -> f.g $ xs)
result = (toDiffList "dog ") `mappend` (toDiffList "meat ") `mappend` (toDiffList "is good!")
<=> result = (xs -> "dog " ++ xs).(xs -> "meat " ++ xs).(xs -> "is good!" ++ xs)
fromDiffList result
<=> "dog " ++ ("meat " ++ ("is good!" ++ []))

16

※fromDiffListを適用したタイミングで右結合で評価される

Open Cloud Campus
第14章 もうちょっとだけモナド

リストの結合を効率的に扱うテクニック
 [String]の代わりにDiffList Stringを使うように書き換えたgcdReverse
$ cat hoge.hs
import Data.Monoid
import Control.Monad.Writer
newtype DiffList a = DiffList { getDiffList :: [a] -> [a] }
toDiffList :: [a] -> DiffList a
toDiffList ys = DiffList (xs -> ys ++ xs)
fromDiffList :: DiffList a -> [a]
fromDiffList (DiffList f) = f []
instance Monoid (DiffList a) where
mempty = DiffList (xs -> [] ++ xs)
(DiffList f) `mappend` (DiffList g) = DiffList (xs -> f.g $ xs)
gcdReverse :: Int -> Int -> Writer (DiffList String) Int
gcdReverse a b
| b == 0
= do
tell (toDiffList ["Finished with " ++ show a])
return a
| otherwise = do
result <- gcdReverse b (a `mod` b)
tell (toDiffList [show a ++ " mod " ++ show b ++
" = " ++ show (a `mod` b)])
return result

※fromDiffListを適用したタイミングで右結合で評価される

$ ghci hoge.hs
*Main> fromDiffList . snd . runWriter $ gcdReverse 110 34
["Finished with 2","8 mod 2 = 0","34 mod 8 = 2","110 mod 34 = 8"]

17

Open Cloud Campus
14.2 Reader? それはあなたです!
第14章 もうちょっとだけモナド

(復習)ファンクタとしての関数 「(->) r」
 「(->) r」は「rからの関数」を作る型コンストラクタ
(->) r a <=> r -> a

 「(->) r」はファンクタ
instance Functor ((->) r) where
fmap f g = f.g

g

f.g

r -> a
(->) r
a

19

fmap f

f

r -> b
(->) r

$ ghci
*Main>
*Main>
*Main>
55
*Main>
55

let f = (*5)
let g = (+3)
fmap f g $ 8
(*5).(+3) $ 8

b

Open Cloud Campus
第14章 もうちょっとだけモナド

(復習)アプリカティブファンクタとしての関数 「(->) r」
 「(->) r」はアプリカティブファンクタ
instance Applicative ((->) r) where
pure x = _ -> x
f <*> g = x -> f x (g x)
-- f :: r -> (a -> b)
-- g :: r -> a
-- f <*> g :: r -> b

注)f <$> x = fmap f x
(+)
<=>
<=>
<=>

(+) <$> (*2) <*> (+10) <=> x -> (x*2) + (x+10)

<$> (*2) <*> (+10)
(+).(*2) <*> (+10)
x -> ((+).(*2) x)((+10) x)
x -> (x*2) + (x+10)

ここに共通のパラメータxを注入するイメージ

(*2)
r -> a

(+) <$>
(fmap (+))

f := (+).(*2)
r -> (a -> b)

<*>

g := (+10)
r -> a
共通のパラメータxが与えられた
ものとして演算する

a
20

(+)

a -> b

x -> f x (g x) <=> x -> (x*2)+(x+10)
Open Cloud Campus
第14章 もうちょっとだけモナド

モナドとしての関数 「(->) r」
 「(->) r」は次の定義でモナドにもなります。
– アプリカティブファンクタの定義と比較すると f の引数の順序が異なるだけで、本質的に
は同じことをしています。
instance Monad ((->) r) where
return x = _ -> x
g >>= f = x -> f (g x) x
-- f :: a -> (r -> b)
-- g :: r -> a
-- g >>= f :: r -> b

instance Applicative ((->) r) where
pure x = _ -> x
f <*> g = x -> f x (g x)
-- f :: r -> (a -> b)
-- g :: r -> a
-- f <*> g :: r -> b

f := w x -> (x*2) + w
g := x+10
g >>= f <=> x -> (x*2) + (x+10)

f := (+).(*2) <=> f := x w -> (x*2) + w
g := x+10
f <*> g <=> x -> (x*2) + (x+10)

同じ結果

21

Open Cloud Campus
第14章 もうちょっとだけモナド

モナドとしての関数 「(->) r」
 モナドにした恩恵として、do記法が使用できます。
– Monadのバインド演算をすべて評価した後に、パラメータxを読んで結果を出すので、
「Readerモナド」と呼ばれます。
$ cat hoge.hs
import Control.Monad.Instances
addStuff :: Int -> Int
addStuff = do
a <- (*2)
b <- (+10)
return (a+b)

instance Monad ((->) r) where
return x = _ -> x
g >>= f = x -> f (g x) x

$ ghci hoge.hs
*Main> addStuff 3
19
addStuff = (*2)
<=> (*2) >>= a
<=> (*2) >>= a
<=> x -> (x*2)

22

>>= a -> ((+10) >>= b -> retrun (a+b))
-> ((+10) >>= b _ -> (a+b))
x -> a + (x+10)
+ (x+10)

Open Cloud Campus
14.3 計算の状態の正体
第14章 もうちょっとだけモナド

状態付きの計算とは?
 関数内部で「外部の状態」を想定することはできないので、外部の状態に依存した
処理をする際は、「外部の状態」を引数として与えます。
– 例えば、関数randomで3つの乱数(Bool値)を取得するなら、次のようになります。 
randomは、乱数の種(ジェネレータ)を取って、乱数と新しい種を返します。
$ cat hoge.hs
import System.Random
-- random :: (RandomGen g, Random a) -> g -> (a, g)
threeCoins :: StdGen -> (Bool ,Bool, Bool)
threeCoins gen =
let (firstCoin, newGen) = random gen
(secondCoin, newGen') = random newGen
(thirdCoin, newGen'') = random newGen'
in (firstCoin, secondCoin, thirdCoin)
$ ghci hoge.hs
*Main> threeCoins (mkStdGen 999)
(True,False,False)

最初の種を作る関数

 これを一般化して、次の型の関数を「状態付きの計算」と呼びます。
– sが「状態」で、aが状態に依存した「計算結果」
s -> (a, s)
24

Open Cloud Campus
第14章 もうちょっとだけモナド

状態付きの計算の例
 「スタックの状態」を受けて、push/pop操作する関数の例です。
$ cat hoge.hs
type Stack = [Int]
pop :: Stack -> (Int, Stack)
pop (x:xs) = (x, xs)
push :: Int -> Stack -> ((), Stack)
push a xs = ((), a:xs)
$ ghci hoge.hs
*Main> let ((), newStack1) = push 3 []
*Main> let (a, newStack2) = pop newStack1
*Main> let ((), newStack1) = push 3 [5,8,2,1]
*Main> let (a, newStack2) = pop newStack1
*Main> pop newStack2
(5,[8,2,1])

25

Open Cloud Campus
第14章 もうちょっとだけモナド

Stateモナド
 状態の受け渡しをバインド演算(>>=)で行えるモナドを構築してみます。
newtype State s a = State { runState :: s -> (a, s) }
instance Monad (State s) where
return x = State $ s -> (x, s)
State g >>= f = State $ s -> let (a, stat) = g s
in runState (f a) stat
--

State g >>= f

= State $ s -> runState (f $ fst (g s)) (snd (g s))

gを実行する直前の状態

s

gが保持する値

26

gを実行した直後の状態

g

a

stat

return xは、「状態は変えず
にxという値を持つ」モナド

f a
f

return x

x

Open Cloud Campus
第14章 もうちょっとだけモナド

StateモナドでStackを実装
 Stateモナドは、Control.Monad.Stateで定義されています。
– 値コンストラクタが「state」(頭が小文字)なので注意。
$ cat hoge.hs
import Control.Monad.State
type Stack = [Int]
pop :: State Stack Int
pop = state $ (x:xs) -> (x, xs)
push :: Int -> State Stack ()
push a = state $ xs -> ((), a:xs)
stackManip :: State Stack Int
stackManip = do
push 3
pop
pop
$ ghci hoge.hs
*Main> runState stackManip $ [5,8,2,1]
(5,[8,2,1])
27

Open Cloud Campus
第14章 もうちょっとだけモナド

StateモナドでStackを実装
 もう少し複雑な例
$ cat hoge.hs
import Control.Monad.State

$ ghci hoge.hs

type Stack = [Int]

*Main> runState stackStuff [9,0,2,1,0]
((),[8,3,0,2,1,0])

pop :: State Stack Int
pop = state $ (x:xs) -> (x, xs)

*Main> runState stackStuff [5,0,2,1,0]
((),[5,0,2,1,0])

push :: Int -> State Stack ()
push a = state $ xs -> ((), a:xs)
stackManip :: State Stack Int
stackManip = do
push 3
pop
pop
stackStuff :: State Stack ()
stackStuff = do
a <- pop
if a == 5 then push 5
else do push 3
push 8
28

Open Cloud Campus
第14章 もうちょっとだけモナド

StateモナドでStackを実装
 getとputで状態の確認と操作ができます。
– getは、現在の状態を値にコピーします。
– putは、現在の状態を指定の状態に強制リセットします。
get = state $ s -> (s, s)
put stat = state $ s -> ((), stat)

 push/popをget/putで実装した例
pop :: State Stack Int
pop = do
(x:xs) <- get
put xs
return x
push :: Int -> State Stack Int
push x = do
xs <- get
put (x:xs)

29

Open Cloud Campus
第14章 もうちょっとだけモナド

Stateモナドの型の注意
 モナドの類は、「*->*」(型パラメータを1つとって、初めて具体型になる)
– 例えば、リストモナド [] は、[Int], [String], [Char]などさまざまな具体型を包括してい
ます。バインド演算を通して、[Int]を取って、[String]を返すなど、型を変換すること
が可能です。
(>>=) :: [a] -> (a -> [b]) -> [b]

 Stateモナドの定義を見ると、「値」の型aが変換可能なパラメータに対応しています。「状
態」の型sは、モナドの定義に固定的に埋め込まれているので、バインド演算で変換すること
はできません。
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs)
newtype State s a = State { runState :: s -> (a, s) }
instance Monad (State s) where
return x = State $ s -> (x, s)
State g >>= f = State $ s -> let (a, stat) = g s
in runState (f a) stat
30

Open Cloud Campus
第14章 もうちょっとだけモナド

乱数の連続生成をStateモナドで実施
 乱数生成関数randomをStateモナドに包むと、乱数の種を「状態」として受け取る
ことができます。
$ cat hoge.hs
import System.Random
import Control.Monad.State
randomSt :: (Random a) => State StdGen a
randomSt = state random
threeCoins :: State StdGen (Bool ,Bool, Bool)
threeCoins = do
a <- randomSt
b <- randomSt
c <- randomSt
return (a, b, c)
$ ghci hoge.hs
*Main> runState threeCoins (mkStdGen 999)
((True,False,False),2063054562 2103410263)

31

Open Cloud Campus
おまけ
StateモナドでWriterモナドを実装
第14章 もうちょっとだけモナド

StateモナドとWriterモナドの比較
 Stateモナドの定義を見ながら・・・
newtype State s a = State { runState :: ( s -> (a, s) ) }
instance Monad (State s) where
return x
= State $ s -> (x, s)
State g >>= f = State $ s -> let (a, stat) = g s
in runState (f a) stat

 Writerモナドの定義を次のように書き直します。
import Data.Monoid
newtype Writer w a = Writer { runWriter :: (a, w) }
instance (Monoid w) => Monad (Writer w) where
return x
= Writer $ (x, mempty)
Writer g >>= f = Writer $ let (a, log) = g
in (fst $ runWriter (f a),
log `mappend` (snd $ runWriter (f a)))

 よく似ています・・・。

33

– Stateモナドは、状態(s)の初期値を受けて、各モナドがその値を変更していきます。一
方、Writerモナドは、ログ(モノイドw)の初期値を受けて、各モナドがログに追記して
いきます。
– つまり、Stateモナドの「状態」にモノイドを指定して、状態の変更操作を「追記」に
限定すると、Writerモナドが得られると想像できます。
Open Cloud Campus
第14章 もうちょっとだけモナド

やってみました
 できました。
$ cat hoge.hs
import Data.Monoid
newtype State s a = State { runState :: ( s -> (a, s) ) }
instance Monad (State s) where
return x
= State $ s -> (x, s)
State g >>= f = State $ s -> let (a, stat) = g s
in runState (f a) stat
tell :: (Monoid w) => w -> State w ()
tell log = State $ s -> ((), s `mappend` log)
logNumber :: Int -> State [String] Int
logNumber x = State $ s -> (x, s `mappend` ["Got number: " ++ show x])
multWithLog :: State [String] Int
multWithLog = do
a <- logNumber 3
b <- logNumber 5
tell ["Gonna multiply these two"]
return (a*b)
$ ghci hoge.hs
*Main> runState multWithLog []
(15,["Got number: 3","Got number: 5","Gonna multiply these two"])

34

Open Cloud Campus
第14章 もうちょっとだけモナド

やってみました
 Writerモナドの場合は、バインド演算に「ログの追加(mappend)」がハード
コードされているので、tell, logNumberでは、追記するログを与えるだけです。
tell :: (Monoid a) => a -> Writer a ()
tell log = writer ((), log)
logNumber :: Int -> Writer [String] Int
logNumber x = writer (x, ["Got number: " ++ show x])

 一方、Stateモナドの場合は、バインド演算時の状態変化は、ユーザが自由に実
装できるので、明示的に`mappend`するように実装しています。
tell :: (Monoid w) => w -> State w ()
tell log = State $ s -> ((), s `mappend` log)
logNumber :: Int -> State [String] Int
logNumber x = State $ s -> (x, s `mappend` ["Got number: " ++ show x])

35

Open Cloud Campus
第14章 もうちょっとだけモナド

Q&A

36

Open Cloud Campus
オープンクラウド・キャンパス

すごいHaskell
たのしく学ぼう!

中井悦司
Twitter @enakai00

More Related Content

What's hot

FNA provime pranuese teste
FNA provime pranuese testeFNA provime pranuese teste
FNA provime pranuese testeArton Feta
 
NotesQueryResultsProcessor.pptx
NotesQueryResultsProcessor.pptxNotesQueryResultsProcessor.pptx
NotesQueryResultsProcessor.pptxHaruyuki Nakano
 
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)Yoichi Nakayama
 
距離まとめられませんでした
距離まとめられませんでした距離まとめられませんでした
距離まとめられませんでしたHaruka Ozaki
 
データとは何か
データとは何かデータとは何か
データとは何かKenta Suzuki
 
BPStudy32 CouchDB 再入門
BPStudy32 CouchDB 再入門BPStudy32 CouchDB 再入門
BPStudy32 CouchDB 再入門Yohei Sasaki
 
コードを書けば複素数がわかる
コードを書けば複素数がわかるコードを書けば複素数がわかる
コードを書けば複素数がわかるTaketo Sano
 
虚数は作れる!Swift で学ぶ複素数
虚数は作れる!Swift で学ぶ複素数虚数は作れる!Swift で学ぶ複素数
虚数は作れる!Swift で学ぶ複素数Taketo Sano
 
Python for Data Analysis: Chapter 2
Python for Data Analysis: Chapter 2Python for Data Analysis: Chapter 2
Python for Data Analysis: Chapter 2智哉 今西
 
はじめてのCouch db
はじめてのCouch dbはじめてのCouch db
はじめてのCouch dbEiji Kuroda
 
RでGISハンズオンセッション
RでGISハンズオンセッションRでGISハンズオンセッション
RでGISハンズオンセッションarctic_tern265
 
第10回 計算機構成
第10回 計算機構成第10回 計算機構成
第10回 計算機構成眞樹 冨澤
 
第12回計算機構成
第12回計算機構成第12回計算機構成
第12回計算機構成眞樹 冨澤
 
ジャパネットQB GPars
ジャパネットQB GParsジャパネットQB GPars
ジャパネットQB GParsTakahiro Sugiura
 
Java9直前!最近のJava復習ハンズオン
Java9直前!最近のJava復習ハンズオンJava9直前!最近のJava復習ハンズオン
Java9直前!最近のJava復習ハンズオンHiroto Yamakawa
 

What's hot (20)

FNA provime pranuese teste
FNA provime pranuese testeFNA provime pranuese teste
FNA provime pranuese teste
 
機械学習
機械学習機械学習
機械学習
 
NotesQueryResultsProcessor.pptx
NotesQueryResultsProcessor.pptxNotesQueryResultsProcessor.pptx
NotesQueryResultsProcessor.pptx
 
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
 
Clojure
ClojureClojure
Clojure
 
RでGIS
RでGISRでGIS
RでGIS
 
距離まとめられませんでした
距離まとめられませんでした距離まとめられませんでした
距離まとめられませんでした
 
データとは何か
データとは何かデータとは何か
データとは何か
 
BPStudy32 CouchDB 再入門
BPStudy32 CouchDB 再入門BPStudy32 CouchDB 再入門
BPStudy32 CouchDB 再入門
 
コードを書けば複素数がわかる
コードを書けば複素数がわかるコードを書けば複素数がわかる
コードを書けば複素数がわかる
 
虚数は作れる!Swift で学ぶ複素数
虚数は作れる!Swift で学ぶ複素数虚数は作れる!Swift で学ぶ複素数
虚数は作れる!Swift で学ぶ複素数
 
Python for Data Analysis: Chapter 2
Python for Data Analysis: Chapter 2Python for Data Analysis: Chapter 2
Python for Data Analysis: Chapter 2
 
はじめてのCouch db
はじめてのCouch dbはじめてのCouch db
はじめてのCouch db
 
RでGISハンズオンセッション
RでGISハンズオンセッションRでGISハンズオンセッション
RでGISハンズオンセッション
 
Perl for visualization
Perl for visualizationPerl for visualization
Perl for visualization
 
第10回 計算機構成
第10回 計算機構成第10回 計算機構成
第10回 計算機構成
 
Gtug girls-20140828
Gtug girls-20140828Gtug girls-20140828
Gtug girls-20140828
 
第12回計算機構成
第12回計算機構成第12回計算機構成
第12回計算機構成
 
ジャパネットQB GPars
ジャパネットQB GParsジャパネットQB GPars
ジャパネットQB GPars
 
Java9直前!最近のJava復習ハンズオン
Java9直前!最近のJava復習ハンズオンJava9直前!最近のJava復習ハンズオン
Java9直前!最近のJava復習ハンズオン
 

Similar to Haskell勉強会 14.1〜14.3 の説明資料

第2回 JavaScriptから始めるプログラミング2016
第2回 JavaScriptから始めるプログラミング2016第2回 JavaScriptから始めるプログラミング2016
第2回 JavaScriptから始めるプログラミング2016kyoto university
 
並行プログラミングと継続モナド
並行プログラミングと継続モナド並行プログラミングと継続モナド
並行プログラミングと継続モナドKousuke Ruichi
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミングOuka Yuka
 
SICP
SICPSICP
SICPS W
 
すごいHaskell楽しく学ぼう-第12章モノイド-
すごいHaskell楽しく学ぼう-第12章モノイド-すごいHaskell楽しく学ぼう-第12章モノイド-
すごいHaskell楽しく学ぼう-第12章モノイド-Hiromasa Ohashi
 
Pythonで始めるDropboxAPI
Pythonで始めるDropboxAPIPythonで始めるDropboxAPI
Pythonで始めるDropboxAPIDaisuke Igarashi
 
今さら始めるCoffeeScript
今さら始めるCoffeeScript今さら始めるCoffeeScript
今さら始めるCoffeeScriptAshitaba YOSHIOKA
 
Adding simpl GVN path into GHC
Adding simpl GVN path into GHCAdding simpl GVN path into GHC
Adding simpl GVN path into GHCKei Hibino
 
多次元配列の効率的利用法の検討
多次元配列の効率的利用法の検討多次元配列の効率的利用法の検討
多次元配列の効率的利用法の検討Yu Sato
 
モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座bleis tift
 
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトEWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトKiyoshi Sawada
 
SGD+α: 確率的勾配降下法の現在と未来
SGD+α: 確率的勾配降下法の現在と未来SGD+α: 確率的勾配降下法の現在と未来
SGD+α: 確率的勾配降下法の現在と未来Hidekazu Oiwa
 
[機械学習]文章のクラス分類
[機械学習]文章のクラス分類[機械学習]文章のクラス分類
[機械学習]文章のクラス分類Tetsuya Hasegawa
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
20170923 excelユーザーのためのr入門
20170923 excelユーザーのためのr入門20170923 excelユーザーのためのr入門
20170923 excelユーザーのためのr入門Takashi Kitano
 
Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Fixstars Corporation
 

Similar to Haskell勉強会 14.1〜14.3 の説明資料 (20)

第2回 JavaScriptから始めるプログラミング2016
第2回 JavaScriptから始めるプログラミング2016第2回 JavaScriptから始めるプログラミング2016
第2回 JavaScriptから始めるプログラミング2016
 
並行プログラミングと継続モナド
並行プログラミングと継続モナド並行プログラミングと継続モナド
並行プログラミングと継続モナド
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
 
SICP
SICPSICP
SICP
 
すごいHaskell楽しく学ぼう-第12章モノイド-
すごいHaskell楽しく学ぼう-第12章モノイド-すごいHaskell楽しく学ぼう-第12章モノイド-
すごいHaskell楽しく学ぼう-第12章モノイド-
 
Pythonで始めるDropboxAPI
Pythonで始めるDropboxAPIPythonで始めるDropboxAPI
Pythonで始めるDropboxAPI
 
今さら始めるCoffeeScript
今さら始めるCoffeeScript今さら始めるCoffeeScript
今さら始めるCoffeeScript
 
Clean
Clean Clean
Clean
 
Clean
Clean Clean
Clean
 
MapReduce入門
MapReduce入門MapReduce入門
MapReduce入門
 
Adding simpl GVN path into GHC
Adding simpl GVN path into GHCAdding simpl GVN path into GHC
Adding simpl GVN path into GHC
 
多次元配列の効率的利用法の検討
多次元配列の効率的利用法の検討多次元配列の効率的利用法の検討
多次元配列の効率的利用法の検討
 
モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座
 
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトEWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
 
SGD+α: 確率的勾配降下法の現在と未来
SGD+α: 確率的勾配降下法の現在と未来SGD+α: 確率的勾配降下法の現在と未来
SGD+α: 確率的勾配降下法の現在と未来
 
[機械学習]文章のクラス分類
[機械学習]文章のクラス分類[機械学習]文章のクラス分類
[機械学習]文章のクラス分類
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
20170923 excelユーザーのためのr入門
20170923 excelユーザーのためのr入門20170923 excelユーザーのためのr入門
20170923 excelユーザーのためのr入門
 
Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門Halide による画像処理プログラミング入門
Halide による画像処理プログラミング入門
 
RGtk2入門
RGtk2入門RGtk2入門
RGtk2入門
 

More from Etsuji Nakai

「ITエンジニアリングの本質」を考える
「ITエンジニアリングの本質」を考える「ITエンジニアリングの本質」を考える
「ITエンジニアリングの本質」を考えるEtsuji Nakai
 
Googleのインフラ技術に見る基盤標準化とDevOpsの真実
Googleのインフラ技術に見る基盤標準化とDevOpsの真実Googleのインフラ技術に見る基盤標準化とDevOpsの真実
Googleのインフラ技術に見る基盤標準化とDevOpsの真実Etsuji Nakai
 
Introducton to Convolutional Nerural Network with TensorFlow
Introducton to Convolutional Nerural Network with TensorFlowIntroducton to Convolutional Nerural Network with TensorFlow
Introducton to Convolutional Nerural Network with TensorFlowEtsuji Nakai
 
Googleにおける機械学習の活用とクラウドサービス
Googleにおける機械学習の活用とクラウドサービスGoogleにおける機械学習の活用とクラウドサービス
Googleにおける機械学習の活用とクラウドサービスEtsuji Nakai
 
Spannerに関する技術メモ
Spannerに関する技術メモSpannerに関する技術メモ
Spannerに関する技術メモEtsuji Nakai
 
Googleのインフラ技術から考える理想のDevOps
Googleのインフラ技術から考える理想のDevOpsGoogleのインフラ技術から考える理想のDevOps
Googleのインフラ技術から考える理想のDevOpsEtsuji Nakai
 
A Brief History of My English Learning
A Brief History of My English LearningA Brief History of My English Learning
A Brief History of My English LearningEtsuji Nakai
 
TensorFlowプログラミングと分類アルゴリズムの基礎
TensorFlowプログラミングと分類アルゴリズムの基礎TensorFlowプログラミングと分類アルゴリズムの基礎
TensorFlowプログラミングと分類アルゴリズムの基礎Etsuji Nakai
 
TensorFlowによるニューラルネットワーク入門
TensorFlowによるニューラルネットワーク入門TensorFlowによるニューラルネットワーク入門
TensorFlowによるニューラルネットワーク入門Etsuji Nakai
 
Using Kubernetes on Google Container Engine
Using Kubernetes on Google Container EngineUsing Kubernetes on Google Container Engine
Using Kubernetes on Google Container EngineEtsuji Nakai
 
Lecture note on PRML 8.2
Lecture note on PRML 8.2Lecture note on PRML 8.2
Lecture note on PRML 8.2Etsuji Nakai
 
Machine Learning Basics for Web Application Developers
Machine Learning Basics for Web Application DevelopersMachine Learning Basics for Web Application Developers
Machine Learning Basics for Web Application DevelopersEtsuji Nakai
 
Your first TensorFlow programming with Jupyter
Your first TensorFlow programming with JupyterYour first TensorFlow programming with Jupyter
Your first TensorFlow programming with JupyterEtsuji Nakai
 
Deep Q-Network for beginners
Deep Q-Network for beginnersDeep Q-Network for beginners
Deep Q-Network for beginnersEtsuji Nakai
 
TensorFlowで学ぶDQN
TensorFlowで学ぶDQNTensorFlowで学ぶDQN
TensorFlowで学ぶDQNEtsuji Nakai
 
DevOpsにおける組織に固有の事情を どのように整理するべきか
DevOpsにおける組織に固有の事情を どのように整理するべきかDevOpsにおける組織に固有の事情を どのように整理するべきか
DevOpsにおける組織に固有の事情を どのように整理するべきかEtsuji Nakai
 
インタークラウドを実現する技術 〜 デファクトスタンダードからの視点 〜
インタークラウドを実現する技術 〜 デファクトスタンダードからの視点 〜インタークラウドを実現する技術 〜 デファクトスタンダードからの視点 〜
インタークラウドを実現する技術 〜 デファクトスタンダードからの視点 〜Etsuji Nakai
 

More from Etsuji Nakai (20)

PRML11.2-11.3
PRML11.2-11.3PRML11.2-11.3
PRML11.2-11.3
 
「ITエンジニアリングの本質」を考える
「ITエンジニアリングの本質」を考える「ITエンジニアリングの本質」を考える
「ITエンジニアリングの本質」を考える
 
Googleのインフラ技術に見る基盤標準化とDevOpsの真実
Googleのインフラ技術に見る基盤標準化とDevOpsの真実Googleのインフラ技術に見る基盤標準化とDevOpsの真実
Googleのインフラ技術に見る基盤標準化とDevOpsの真実
 
Introducton to Convolutional Nerural Network with TensorFlow
Introducton to Convolutional Nerural Network with TensorFlowIntroducton to Convolutional Nerural Network with TensorFlow
Introducton to Convolutional Nerural Network with TensorFlow
 
Googleにおける機械学習の活用とクラウドサービス
Googleにおける機械学習の活用とクラウドサービスGoogleにおける機械学習の活用とクラウドサービス
Googleにおける機械学習の活用とクラウドサービス
 
Spannerに関する技術メモ
Spannerに関する技術メモSpannerに関する技術メモ
Spannerに関する技術メモ
 
Googleのインフラ技術から考える理想のDevOps
Googleのインフラ技術から考える理想のDevOpsGoogleのインフラ技術から考える理想のDevOps
Googleのインフラ技術から考える理想のDevOps
 
A Brief History of My English Learning
A Brief History of My English LearningA Brief History of My English Learning
A Brief History of My English Learning
 
TensorFlowプログラミングと分類アルゴリズムの基礎
TensorFlowプログラミングと分類アルゴリズムの基礎TensorFlowプログラミングと分類アルゴリズムの基礎
TensorFlowプログラミングと分類アルゴリズムの基礎
 
TensorFlowによるニューラルネットワーク入門
TensorFlowによるニューラルネットワーク入門TensorFlowによるニューラルネットワーク入門
TensorFlowによるニューラルネットワーク入門
 
Using Kubernetes on Google Container Engine
Using Kubernetes on Google Container EngineUsing Kubernetes on Google Container Engine
Using Kubernetes on Google Container Engine
 
Lecture note on PRML 8.2
Lecture note on PRML 8.2Lecture note on PRML 8.2
Lecture note on PRML 8.2
 
Machine Learning Basics for Web Application Developers
Machine Learning Basics for Web Application DevelopersMachine Learning Basics for Web Application Developers
Machine Learning Basics for Web Application Developers
 
Your first TensorFlow programming with Jupyter
Your first TensorFlow programming with JupyterYour first TensorFlow programming with Jupyter
Your first TensorFlow programming with Jupyter
 
Deep Q-Network for beginners
Deep Q-Network for beginnersDeep Q-Network for beginners
Deep Q-Network for beginners
 
Life with jupyter
Life with jupyterLife with jupyter
Life with jupyter
 
TensorFlowで学ぶDQN
TensorFlowで学ぶDQNTensorFlowで学ぶDQN
TensorFlowで学ぶDQN
 
DevOpsにおける組織に固有の事情を どのように整理するべきか
DevOpsにおける組織に固有の事情を どのように整理するべきかDevOpsにおける組織に固有の事情を どのように整理するべきか
DevOpsにおける組織に固有の事情を どのように整理するべきか
 
PRML7.2
PRML7.2PRML7.2
PRML7.2
 
インタークラウドを実現する技術 〜 デファクトスタンダードからの視点 〜
インタークラウドを実現する技術 〜 デファクトスタンダードからの視点 〜インタークラウドを実現する技術 〜 デファクトスタンダードからの視点 〜
インタークラウドを実現する技術 〜 デファクトスタンダードからの視点 〜
 

Recently uploaded

クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案sugiuralab
 

Recently uploaded (9)

クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
 

Haskell勉強会 14.1〜14.3 の説明資料