86
Haskell 進進進進進進進進 snowmantw @gmail.com 20120714 Functional Programming SIG

Introduction to Basic Haskell Components (In Chinese)

Embed Size (px)

Citation preview

Page 1: Introduction to Basic Haskell Components (In Chinese)

Haskell 進階運算元件介紹snowmantw @gmail.com

20120714 Functional Programming SIG

Page 2: Introduction to Basic Haskell Components (In Chinese)

http://goo.gl/VInp9

MS PowerPoint 2007 PDF

http://goo.gl/TiiMY本著作係採用 CC - - 2.0 創用 姓名標示 非商業性 相同方式分享 台灣 授權條款授權 .

Page 3: Introduction to Basic Haskell Components (In Chinese)

Snowmantw: Vimmer / Linux User λ Haskell Learner G Self-Studier $ Javascript Developer @ snowmantw at gmail.com

✍Master's Degree Student → Dept. of Computer Science, NCCU snowmantw.github.com

C C++

PHP JS Haskell Java

Page 4: Introduction to Basic Haskell Components (In Chinese)

Outline• YAMI – Yet Another Monad Introduction• Monad vs. Arrow• Other Type Classes in Typeclassopedia• Beyond Haskell – Patterns in Functional Programming

Page 5: Introduction to Basic Haskell Components (In Chinese)

Yet Another Monad Introduction

Page 6: Introduction to Basic Haskell Components (In Chinese)

What is a Monad ?

Page 7: Introduction to Basic Haskell Components (In Chinese)

What is a Monad ?getLine :: IO StringputStrLn:: String -> IO ()(>>) :: Monad m => m a -> m b -> m b(>>=) :: Monad m => m a -> (a -> m b) -> m b

main = getLine >>= \ name -> putStrLn “Hello :”++name >> putStrLn “World !”

這大概是為何大部分的 Haskell “Hello World” 都是…從費式級數開始講起

Page 8: Introduction to Basic Haskell Components (In Chinese)

Tears of a Haskell Newbie

Monad ,單元( unit )的拉丁語,來自範疇論的一種技術,其已經被採用作為處理在…功能性程序設計語言中

In functional programming, a monad is a structure that represents computations.

In category theory, a branch of mathematics, a monad, Kleisli triple, or triple is an (endo-)functor, together with two natural transformations.

A monad is an "amplifier" of types that obeys certain rules and which has certain operations provided.

單子( monad ,也譯單體)是函數式編程中的一種抽象數據類型,其特別之處在於,它是用來表示計算而不是數據的。在以函數式風格編寫的程序中,單子可以用來組織包含有序操作的過程,或者用來定義任意的控制流

Page 9: Introduction to Basic Haskell Components (In Chinese)

Monad ,單元( unit )的拉丁語,來自範疇論的一種技術,其已經被採用作為處理在…功能性程序設計語言中

In functional programming, a monad is a structure that represents computations.

In category theory, a branch of mathematics, a monad, Kleisli triple, or triple is an (endo-)functor, together with two natural transformations.

A monad is an "amplifier" of types that obeys certain rules and which has certain operations provided.

單子( monad ,也譯單體)是函數式編程中的一種抽象數據類型,其特別之處在於,它是用來表示計算而不是數據的。在以函數式風格編寫的程序中,單子可以用來組織包含有序操作的過程,或者用來定義任意的控制流

Tears of a Haskell Newbie

Page 10: Introduction to Basic Haskell Components (In Chinese)

Monad everywhere and not a piece to understand…

Tears of a Haskell Newbie

Page 11: Introduction to Basic Haskell Components (In Chinese)

There is no royal road to Haskell. —Euclid*

Tears of a Haskell Newbie

*from “typeclassopedia”

Page 12: Introduction to Basic Haskell Components (In Chinese)

“Typeclassopedia” in Monad.Reader # 13

http://www.haskell.org/wikiupload/8/85/TMR-Issue13.pdf

Page 13: Introduction to Basic Haskell Components (In Chinese)

Begin from Pure Functions

Page 14: Introduction to Basic Haskell Components (In Chinese)

Begin from Pure Functions

fn:: a -> bgn:: b -> cgfn:: a -> cgfn a = gn ( fn ( a ) )

We can use “definition” to make new functions.

But that’s not so “functional”.

Page 15: Introduction to Basic Haskell Components (In Chinese)

Composition in Functional Language

(.):: (b -> c)->(a -> b)-> a -> c

fngn 。 gfnFunctional Language ( at least, in Haskell ) :

Compose Everything !

Page 16: Introduction to Basic Haskell Components (In Chinese)

Composition in Functional Language

大的函式可由許多小函式合成而成zn . yn . xn …. cn . bn . an

Page 17: Introduction to Basic Haskell Components (In Chinese)

Problem: Data in a Nutshell

Page 18: Introduction to Basic Haskell Components (In Chinese)

Problem: Data in a Nutshell

(+4).(+5):: Int -> Int

Int: 4 Int: 12

((+4).(+5)) 4 == 12

+4 +5

When Int: 4 ~> [Int: 4]

Page 19: Introduction to Basic Haskell Components (In Chinese)

Problem: Data in a Nutshell

(+4).(+5):: Int -> Int

[Int]: [4]

((+4).(+5)) [4] -- Error !

+4 +5 X

函式無法處理帶 context 性質的值 每種 context 都有其意義

Page 20: Introduction to Basic Haskell Components (In Chinese)

Problem: Data in a Nutshell

• Maybe a:: 代表不確定性運算• Either e a:: 代表有可能會例外的運算• [a]:: 代表不確定性運算 -- 可能性更多• IO a:: 代表會對 RealWorld 做出影響

常見的 Context

使用 context 觀點會比容器觀點更加適切

Page 21: Introduction to Basic Haskell Components (In Chinese)

Problem: Data in a Nutshell

(+4).(+5):: Int -> Int

Solution #1

plus45 = (+4).(+5)plus45Special [ x ] = plus45 x -- use pattern matching

“為該函式定義一特別的 unwrap” 版本

有多少 context …就要定義多少版本

Page 22: Introduction to Basic Haskell Components (In Chinese)

Problem: Data in a Nutshell

(+4).(+5):: Int -> Int

Solution #1

plus45 = (+4).(+5)plus45Special [ x ] = plus45 x plus45SpMaybe (Just x) = plus45 xplus45SpIO (IO x) = plus45 x……..

Page 23: Introduction to Basic Haskell Components (In Chinese)

Problem: Data in a Nutshell

(+4).(+5):: Int -> Int

Solution #1

plus45 = (+4).(+5)plus45Special [ x ] = plus45 x plus45SpMaybe (Just x) = plus45 xplus45SpIO (IO x) = plus45 x……..

pure

with context

實際上分為處理 context 與運算兩部分

Page 24: Introduction to Basic Haskell Components (In Chinese)

Problem: Data in a Nutshell

(+4).(+5):: Int -> Int

Solution #2 每種 context 定義出自己的包裹函式代為處理包裹與「解包」的問題

(+4).(+5)[ 4 ] 4 12 [ 12 ]

fmap:: (a->b)->f a -> f b

Page 25: Introduction to Basic Haskell Components (In Chinese)

Problem: Data in a Nutshell

(+4).(+5):: Int -> Int

Solution #2

重用:不用更改原本的運算函式 解耦:將運算與 context 處理分開靈活:組合而非定義生成新的運算方式

fmap:: (a->b)->f a -> f b

Page 26: Introduction to Basic Haskell Components (In Chinese)

Type Class: FunctorAbstract Structure with fmap

Page 27: Introduction to Basic Haskell Components (In Chinese)

Type Class: Functor

from Typeclassopedia, Haskell Wiki http://www.haskell.org/haskellwiki/Typeclassopedia

Page 28: Introduction to Basic Haskell Components (In Chinese)

Type Class: Functorclass Functor f wherefmap:: ( a -> b ) -> f a -> f b

帶有 fmap 函式定義的 contextfmap 的定義要懂得包裹與解包

fmap = map -- Functor [ ]

fmap _ Nothing = Nothingfmap f ( Just a ) = Just ( f a ) -- Functor Maybe

fmap f x = x >>= ( return . f) -- * Functor IO

Page 29: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad

Functor 定義了如何讓普通函式「轉成」 特定 context 下的函式

fmap:: (a->b)->f a -> f b

(.):: (b -> c)->(a -> b)-> a -> c

Compose 定義了如何串出更大的運算

結合兩者可做出更大的 context 運算

Page 30: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad

從一個普通值帶到某 context 運算

4 → [ 4 ] [ 21 ]

(+4).(+5)

(+4).(+5)

(+4).(+5)

值一但被包裹理論上就不會被解包 ( 特例 )這整條運算: a -> m a ( m :: Context ) 可稱為 action ( from IO Monad )

fmap AND (.)

Page 31: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad

還缺少把值變成 context 值的抽象函式

4 → [ 4 ] [ 21 ]

(+4).(+5)

(+4).(+5)

(+4).(+5)

return:: a -> m a* 這個名字很不幸與許多程式語言的保留關鍵字相同,然而應該 注意其意義幾乎完全不同!* return 幾乎就等於 Data Constructor 了,例如 Just a

[ a ] -> [ c ]

Page 32: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad

不僅僅是 [ ] :抽象概念互通

4 → [ 4 ] [ 31 ]

(+4).(+5)

(+4).(+5)

(+4).(+5)

4 → Maybe 4 Maybe 314 → IO 4 IO 31

m a -> m c

都是從一個值 -> 運算後且 帶 context 的值

Page 33: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad

我們用 fmap (.) 與 return 建出單個 context 運 算

(+4).(+5)

(+4).(+5)

(+4).(+5)

理論上這樣的運算,應該要像函式可以組合。( ) ( )

Page 34: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad

阻礙:型別不通。( ) ( )[ c ]

c -> [ d ]

(>>=):: m a -> (a -> m b ) -> m b這個奇怪的 bind 運算子幫我們搭了橋

Page 35: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad 有了 bind 運算子我們可以任意組合同型 context 運算。( ) ( )

[ c ]

c -> [ d ]

(>>=):: m a -> (a -> m b ) -> m b 效果:把前一個 context 值私下解包後,傳給下個運算

Page 36: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad

。( ) ( )[ c ]

c -> [ d ]

(>>=):: m a -> (a -> m b ) -> m b

find even [1,2] >>= return . ((!!) [1,2,4]) -- Maybe[‘3’,’4’,’5’]>>= digitToInt >>= return . even -- [ ]getLine >>= putStr.((++) “Hi, user [”) >> putStrLn “] !” -- IO

Page 37: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad

(>>=):: m a -> (a -> m b ) -> m bfind even [1,2] >>= return . ((!!)

[1,2,4])找到為偶數的值: Just 2

找到 index#2 的值,並包裝之

find:: (a->Bool)->[a]->Maybe aeven:: Integral a => a -> Bool(!!):: [a]->Int->a ; (!!) [1,2,4] :: Int -> areturn:: a -> m a ; return . ( (!!) [1,2,4] ) :: Int -> m b

return 夠抽象,所以可以視其正在 哪個 context 中用不同的

instance

Page 38: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad

(>>=):: m a -> (a -> m b ) -> m b[‘3’,’4’,’5’]>>= return . digitToInt >>= return . even

( 為了方便示範 )

各字元轉換成整數 各 奇偶數轉成Bool

getLine >>= putStr.((++) “Hi, user [”) >> putStrLn “] !” 從 IO 取得一行 組合傳入字串並從 IO 輸出 不管前面結果而印出

抽象:注意每個 context 對 bind 詮釋都不同,但用法都相同bind 表現的效果之一是不用管傳值,只要專注把運算組合即可(>>):: m a -> m b -> m b -- 不管前面結果,自己執行出 m b

Page 39: Introduction to Basic Haskell Components (In Chinese)

From Functor to Monad

Functor -- fn -> context fnfmap:: (a -> b) -> f a -> f b

Monad -- computation under mreturn:: a -> m a(>>=):: m a-> (a->m b)-> m b 理論上所有 Monad 都要同時也是 Functor ,但並非 Haskell 現狀

Page 40: Introduction to Basic Haskell Components (In Chinese)

Monad LawsLeft identity: return a >>= f ≡ f aRight identity: m >>= return ≡ mAssociativity: (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)

主要是確保組合小運算成大運算的過程中,不會因組合先後不同而出錯

http://www.haskell.org/haskellwiki/Monad_Laws

Page 41: Introduction to Basic Haskell Components (In Chinese)

Monad 與 Pure• Pure: →  函式無副作用 輸入只能根據輸出唯一決定

openFile:: FilePath -> IOMode -> IO HandleIn what sense is the IO monad pure ?

id 3 == 3id 3 == 3id 3 == 3

id 3 = 3id 3 = 3id 3 = 4Hidden State !

Page 42: Introduction to Basic Haskell Components (In Chinese)

Monad 與 Pure: IO MonadopenFile:: FilePath -> IOMode -> IO Handle

In what sense is the IO monad pure ?modify = openFile "/tmp/test" WriteMode >>= (\h -> hPutStrLn h “watch#2: Hello World !" >> hClose h)

watch = openFile "/tmp/test" ReadMode >>= (\h-> hGetLine h >>= putStrLn >> hClose h)

f = watch >> modify >> watch

----

watch#1: Original Contentwatch#2: Hello World !

兩次 watch 呼叫參數都一樣,但是輸出卻不同!

Page 43: Introduction to Basic Haskell Components (In Chinese)

Monad 與 Pure: IO Monad

fn:: a -> a’ ; gn:: a’ -> a’’ ; hn:: a’’ -> a’’’hgfn:: a ~> a’ ~> a’’~> a’’’ :: a -> a’’’

Pure 函式本身不能存有狀態,但是狀態可以用傳遞的方式給予

Haskell ( GHC ) 底層偷偷在 IO Monad 中 間加入傳遞 #RealWorld 的動作

→ modify:: #RealWorld -> #RealWorld’ → watch:: #RealWorld

“Problem ?”

Page 44: Introduction to Basic Haskell Components (In Chinese)

Monad 與 Pure: IO Monad

watch >> modify >> watch -- 將變成類似於(非實際實做!)watch #RealWorld ~> modify #RealWorld ~> watch #RealWorld ’

Pure 函式本身不能存有狀態,但是狀態可以用傳遞的方式給予

所以兩次 watch 的「參數」已經不同,故表面 上看來具有副作用的 watch 實際上也是 Pure

→ 不過我們可解釋 Pure 為:有副作用者,如檔案內容這種值,不能直接「污染」 Pure 函式→ 也就是 Pure Function 與 Action 不能混用

Page 45: Introduction to Basic Haskell Components (In Chinese)

Monad 與 Pure: IO Monad

[a] -> a --:: head, tail, foldl, maximum, minimum …Maybe a -> a --:: fromJust, fromMaybe defaultValue …----IO a -> a --:: ( NO SUCH FUNCTION !! )

Haskell 利用 context 概念永久包住帶 「副作用」的 IO 值: a -> IO a -> …… IO

z

一般 Monad 多少都有 unwrap function ,也 就是在該 context 內部可以是 Impure 的處理。但 離開 context 的值必須只能是 Pure : m

a -> a → 一入 IO ,永為 IO :因沒有unwrapper ,所有要處理 IO 者都必須嵌入該context 內

Page 46: Introduction to Basic Haskell Components (In Chinese)

Monad 小結Pure Function 。with Context

value wrapper :: a -> m a

>>=( ) ( )[ c ]

c -> [ d ]

Page 47: Introduction to Basic Haskell Components (In Chinese)

Monad 小結• Monad 就是符合規則且實作 return 、 >>= 等的

抽象結構 ( Type Class)• 這個抽象結構允許透過組合,產生出新的 action • action :允許將純值包裹進某個 context ,並進行一連串變換的運算• Monad 提供工具將帶 context 運算組合再一起。

包括帶真正 Side-Effect 的 IO 也可以此達到pure

補充: In what sense is the IO monad pure ?http://stackoverflow.com/questions/4063778/in-what-sense-is-the-io-monad-pure

Page 48: Introduction to Basic Haskell Components (In Chinese)

Monad vs. Arrow

Page 49: Introduction to Basic Haskell Components (In Chinese)

Arrow 介紹

from Typeclassopedia, Haskell Wiki http://www.haskell.org/haskellwiki/Typeclassopedia

Page 50: Introduction to Basic Haskell Components (In Chinese)

How to make an ArrowThis is a normal function…

fn:: a -> b… and this is an Arrow

fn::(->) a bJust like any other data type

Maybe[ ] Int Book Id Price

- 這個 Arrow -接收: a給出: b

Tip: 可以表達運算與可以執行運算是兩件事

Page 51: Introduction to Basic Haskell Components (In Chinese)

From Monad to ArrowgetLine :: IO StringputStr, putStrLn :: IO ()

main :: IO ()main = getLine >>= putStr.((++) “Hi, user [”) >> putStrLn “] !”

Monad 型別意義: m a 代表「這個 monad 會產生 a 型別 的值 」因此, Monad 封裝出完整、不依賴外部的 operation ( 所以叫「單子」

) 持有一個 Monad a: 持有一個「值」 ( 內部一連串運算得出)

Arrow 型別意義: a b c 代表「這個 arrow 接收 b 傳出 c 」因此, Arrow 封裝的是一個 transformation ( 有接受端)

持有一個 Arrow b c: 持有一個「會從 b 到 c 的變換」→ 若以 `b` Apply 此 Arrow ,就等於 ( M b ) ( Arrow 不一定都可Apply)Monad 把資料連同運算封裝,模糊了 object 與transformationArrow 只封裝運算,並提供了「針對運算的運算」

Page 52: Introduction to Basic Haskell Components (In Chinese)

From Monad to Arrow 一如 Monad 有抽象的 return 代替實際的建構式, Arrow 中arr:: Arrow a => (b -> c) -> a b c

如何將一個普通的函式封成其 context 下一個 transformation 實做視其 context (運算種類)不同而異

幾個常見的 Arrow

ordinary functions : (->) b cKleisli arrows : Monad m => (->) b m cstream transformers : (-> ) (Stream b) (Stream c)

return:: a -> m a 對比於 Monad 的 return function

將值,而非運算轉換

Page 53: Introduction to Basic Haskell Components (In Chinese)

Arrows: A General Interface to Computation 如果我們有一堆的 Arrow

a b c我們可以針對他們進行一些組合動作

a b d a c d

a b c >>> a c d :: a b d(c -> d) 。 (b -> c):: (->)

b dordinary functions: 就是普通的函式合成Kleisli: 用 g b >>= f 去作組合

Page 54: Introduction to Basic Haskell Components (In Chinese)

Arrows: A General Interface to Computation

基本的 Arrow 函式

http://www.soi.city.ac.uk/~ross/papers/fop.html

Page 55: Introduction to Basic Haskell Components (In Chinese)

Arrows: A General Interface to Computation

使用 Arrow 組合出整個程式

http://www.soi.city.ac.uk/~ross/papers/fop.html

使用 Arrow ,整個程式的邏輯單元就可以像電路一樣被組合

Page 56: Introduction to Basic Haskell Components (In Chinese)

Arrow vs. Monad

Monad 的「中間環節」可脫離型別掌握m a >>= (a -> m b) >>= ( b -> m c )

並無法確認 (a -> m b) 這個 Action 處理中保持在同樣的 context 裡

a m bn c ?

只認頭與尾無法控管中間

Page 57: Introduction to Basic Haskell Components (In Chinese)

Arrow vs. Monad

Arrow 的組合函式會確保 context 相同a b c >>> a c d >>> a d e >>> a e f

a c d 只能再次由 >>> 構成:a c z >>> a z y >>> a y x >>> a x d

a z y 只能再次由 >>> 構成:a z w >>> a w v >>> a v u >>> a u y

Page 58: Introduction to Basic Haskell Components (In Chinese)

Arrow vs. Monad

Arrow 的組合函式會確保 context 相同a b c >>> a c d >>> a d e >>> a e f

a c z >>> a z y >>> a y x >>> a x d

a z w >>> a w v >>> a v u >>> a u y

組合中所有子 Arrow 都在 a 這個 context 內

Page 59: Introduction to Basic Haskell Components (In Chinese)

Arrow vs. Monad

Arrow 的組合函式會確保 context 相同Every time we sequence two monadic computations,we have an opportunity to run arbitrary Haskell code in between them.

Monad

But in the case of arrows, in contrast, the second argument of (>>>) is just an arrow…

Arrow

from “Programming with Arrows”; John Hughes

Page 60: Introduction to Basic Haskell Components (In Chinese)

Other Type Classes in Typeclassopedia

Page 61: Introduction to Basic Haskell Components (In Chinese)

其他運算元件介紹

from Typeclassopedia, Haskell Wiki http://www.haskell.org/haskellwiki/Typeclassopedia

Page 62: Introduction to Basic Haskell Components (In Chinese)

Applicative

Page 63: Introduction to Basic Haskell Components (In Chinese)

ApplicativeFunctor : 可以讓一個函式被「 context 化」

(+4).(+5)[ 4 ] 4 12 [ 12 ]

fmap:: (a->b)->f a -> f b

但是僅限於只有一個參數的函式

Page 64: Introduction to Basic Haskell Components (In Chinese)

Applicativefmap 的函式如何給予一個以上的參數?

(+):: Int -> (Int -> Int)fmap (+) :: f a -> f (Int -> Int)

fn = fmap (+) -- 假設以 [] 為 contextfn:: [ ] Integer -> [ Integer -> Integer ]fn [4] :: [Integer -> Integer] -- 無法進一步 apply [5] 給 (+)fn [4] [5] -- Error ! ( fn [4] 「滿了」,已經無法再給參數)

Page 65: Introduction to Basic Haskell Components (In Chinese)

ApplicativeApplicative 提供了如何 apply 的解決方式

pure :: a -> f a(<*>) :: f (a -> b) -> f a -> f b

fn = fmap (+) -- 假設以 [] 為 contextfn:: [ ] Integer -> [ Integer -> Integer ]fn [4] :: [Integer -> Integer] -- 無法進一步 apply [5] 給 (+)(<*>) (fn [4]) :: [ ] Integer -> [ ] Integer -- 可以給予參數了!fmap (+) [4] <*> [5] -- [9]

將被放在 context 內的變換轉出來,變成可給予的參數

Page 66: Introduction to Basic Haskell Components (In Chinese)

Applicative根據 Applicative Laws , fmap 可換成

fmap g x = pure g <*> x

fn :: a -> b -> c -> d -> e -> f … -> z -- 很多參數 fn a b c d e … -- 一般的 function applypure fn <*> f a <*> f b <*> f c <*> f d <*> f e … -- 就如同往常的 function apply fmap fn f a <*> f b <*> f c <*> f d <*> f e … -- fmap 會幫忙帶第一個參數

因此一般來說 Applicate 使用起來會長得像是給定第一個參數

Page 67: Introduction to Basic Haskell Components (In Chinese)

Monoid

Page 68: Introduction to Basic Haskell Components (In Chinese)

Monoid

Monoid: 可以作「加法」的類別mzero :: m a -- [ ] , Nothingmplus :: m a -> m a -> m a -- (++)

Nothing `mplus` Nothing = Nothing -- 0 solutions + 0 solutions = 0 solutionsJust x `mplus` Nothing = Just x -- 1 solution + 0 solutions = 1 solutionNothing `mplus` Just x = Just x -- 0 solutions + 1 solution = 1 solutionJust x `mplus` Just y = Just x -- 1 solution + 1 solution = 2 solutions,

Maybe 的 mplus 定義有點繁瑣

http://stackoverflow.com/questions/4504489/monadplus-definition-for-haskell-io

* 「為何 IO 不是 MonadPlus ? 」 -> ‘mzero’ would necessarily represent an IO computation that never returns.

Page 69: Introduction to Basic Haskell Components (In Chinese)

Foldable

Page 70: Introduction to Basic Haskell Components (In Chinese)

Foldable

Foldable :可以從一個結構 -> 「加」成一個值fold :: Monoid m => t m -> m

Prelude> foldr (\x y -> concat ["(",x,"+",y,")"]) "0" (map show [1..13]) "(1+(2+(3+(4+(5+(6+(7+(8+(9+(10+(11+(12+(13+0)))))))))))))"   Prelude> foldl (\x y -> concat ["(",x,"+",y,")"]) "0" (map show [1..13]) "(((((((((((((0+1)+2)+3)+4)+5)+6)+7)+8)+9)+10)+11)+12)+13)"

Page 71: Introduction to Basic Haskell Components (In Chinese)

Traversable

Page 72: Introduction to Basic Haskell Components (In Chinese)

Traversable

Foldable 會改變最終結果的結構,與原本不同Traversable 可以給出「保持結構的變化」

traverse :: Applicative f => (a -> f b) -> t a -> f (t b)instance Traversable Tree where traverse g Empty = pure Empty traverse g (Leaf x) = Leaf <$> g x traverse g (Node l x r) = Node <$> traverse g l <*> g x <*> traverse g r

如何把一個改變的函式 apply 到一個結構,及其子結構內?

A

B

C

traverse (+1)

A+1

B+1

C+1

~>

Page 73: Introduction to Basic Haskell Components (In Chinese)

Comonad

Page 74: Introduction to Basic Haskell Components (In Chinese)

Comonad前面說過一般而言 Monad 是「包裹」用return :: a -> f areturn a ~> f a ~> f b ~> f c具有反向「解包」者稱為 Comonadextract :: f a -> a可以從一個 Monad 中解出 pure 的值

Page 75: Introduction to Basic Haskell Components (In Chinese)

Comonad除此之外還有「反向的」 bind ( >>= )extend :: ( w a -> b) -> w a -> w b(>>=):: m a -> ( a -> m b ) -> m b

Page 76: Introduction to Basic Haskell Components (In Chinese)

More on…

http://www.haskell.org/haskellwiki/Typeclassopedia

Page 77: Introduction to Basic Haskell Components (In Chinese)

Beyond HaskellPatterns in Functional Programming

Page 78: Introduction to Basic Haskell Components (In Chinese)

Beyond Haskell• Type Class, (.), Monad, Foldable, Traversable…• 這些概念並非只存在於 Haskell 這個語言中• 甚至並非僅存在於 Functional Programming 的世界中First-Class Function

class Add {int _a;

public:Add(int a): _a(a){}

int operator()(int b){return _a + b;

}};

Add a = Add(3); a(4)

a = (+) 3a 4

Page 79: Introduction to Basic Haskell Components (In Chinese)

Beyond Haskell• Type Class, (.), Monad, Foldable, Traversable…• 這些概念並非只存在於 Haskell 這個語言中• 甚至並非僅存在於 Functional Programming 的世界中

class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool

public interface Eq<A>{ public Boolean eq( A a ); public Boolean neq( A a );}

instance Eq Integer where x == y = x `integerEq` y

public class Integer implements Eq{

//…}

Type Class

Page 80: Introduction to Basic Haskell Components (In Chinese)

Beyond Haskell• Type Class, (.), Monad, Foldable, Traversable…• 這些概念並非只存在於 Haskell 這個語言中• 甚至並非僅存在於 Functional Programming 的世界中

hn = fn . gn

Composition

Command + Compoisite pattern

Page 81: Introduction to Basic Haskell Components (In Chinese)

Beyond Haskell• Type Class, (.), Monad, Foldable, Traversable…• 這些概念並非只存在於 Haskell 這個語言中• 甚至並非僅存在於 Functional Programming 的世界中Monadmain = getLine >>= putStr.((++) “Hi, user [”) >> putStrLn “] !”

$(dom).find(‘.subdom’) .hide() .append(some_dom) .addClass(‘show’); .fadeIn()

http://importantshock.wordpress.com/2009/01/18/jquery-is-a-monad/

“jQuery is a monad”

…OR any fluent interface + context computation

http://en.wikipedia.org/wiki/Fluent_interface

Page 82: Introduction to Basic Haskell Components (In Chinese)

Beyond Haskell• Type Class, (.), Monad, Foldable, Traversable…• 這些概念並非只存在於 Haskell 這個語言中• 甚至並非僅存在於 Functional Programming 的世界中Monadmain = getLine >>= putStr.((++) “Hi, user [”) >> putStrLn “] !”

“Monad in Scala”

“Monad in F#”

“Monad in Java” (some terrible codes )

“Monad in C++”(with C++11 lambda)

“Monad in Ruby”(lambda, again)

“Monad in Python”( 「 with-nice-syntax 」 )

Page 83: Introduction to Basic Haskell Components (In Chinese)

Beyond Haskell• 反過來說,很多所謂 Design Pattern 都是為了 OOP 的概念或語言而設計的• 有些 pattern 到了 Haskell 或 FP 就不見得需要,或變得是語言自然的一部分

Pattern in HaskellStrategy First class functions and lambdasFactory MethodTemplate Method Higher-order functions

Abstract FactoryBuilderBridge

Type classes and smart constructors

AdapterDecoratorChain of Responsibility.

Composition and lifting ( like fmap )

http://blog.ezyang.com/2010/05/design-patterns-in-haskel/

Page 84: Introduction to Basic Haskell Components (In Chinese)

Beyond Haskell• 反過來說,很多所謂 Design Pattern 都是為了 OOP 的概念或語言而設計的• 有些 pattern 到了 Haskell 或 FP 就不見得需要,或變得是語言自然的一部分

Pattern in HaskellVisitor Equational functions; Foldable.

Interpreter Functions; DSEL; ADT provides a nice way to construct the AST of your language.

Command Monads ( computation )Iterator Lazy listsPrototype ImmutabilityFlyweight Memoising and constant applicative forms

(CAF)

http://blog.ezyang.com/2010/05/design-patterns-in-haskel/

Page 85: Introduction to Basic Haskell Components (In Chinese)

Beyond Haskell• 反過來說,很多所謂 Design Pattern 都是為了 OOP 的概念或語言而設計的• 有些 pattern 到了 Haskell 或 FP 就不見得需要,或變得是語言自然的一部分

Pattern in HaskellStateMemento Unnecessary ( LOL ); Undo Monad

Singleton Unnecessary ( again )Facade FunctionsObserver STM, Mvar, Channel

functional reactive programming Proxy Wrapped data types, laziness and garbage

collectorMediator Monad stack

Page 86: Introduction to Basic Haskell Components (In Chinese)

Thanks for your attention.