Hi Haskell
<ul><li>“ A language that doesn’t effect how you think about programming is not worth learning” </li></ul>Alan Perlis
提纲 <ul><li>概述 </li></ul><ul><li>若干语言特性(是什么让 Haskell 如此独特?) </li></ul><ul><ul><li>Lambda , Curry </li></ul></ul><ul><ul><li...
编程范式 (Programming Paradigm) <ul><li>令一门编程语言区别于其它语言的根本在于它所提供的编程范式 </li></ul><ul><li>编程范式指的是编程活动中所遵循的根本风格。它包括选取何种基本元素来构成程序(比...
你知道并用过多少种编程范式? <ul><li>Imperative </li></ul><ul><li>Declarative </li></ul><ul><li>Object-Oriented </li></ul><ul><li>Aspect...
其实还有更多!
Functional Programming <ul><li>在 FP 这种编程范式里,计算是通过对函数的求值 (evaluation) 来组织的,它尽量避免涉及状态与可变 (mutable) 数据。 FP 强调的是函数的施用 (applica...
<ul><li>简单来说 ,Haskell  是一门通用的、静态强类型的、 </li></ul><ul><li>pure (该叫纯粹还是纯洁呢? ) 的、函数式编程语言。 </li></ul><ul><li>它提供的最基本的编程范式是 FP ,...
Lambda 表达式(匿名函数) <ul><li>(x y->x*10+y) 5 9 </li></ul><ul><li>--59 </li></ul><ul><li>大部分时候可以象动态语 </li></ul><ul><li>言那样不写类型声...
First-Class Function & High Order Function <ul><li>函数是语言中的一等公民,意味着它享有和 Int 、 Float 这些基本类型一样的公民权利: </li></ul><ul><ul><li>函数...
Currying(Partial Application)&High Order  <ul><li>-- f::Int->Int->Int </li></ul><ul><li>-- f::Int->(Int->Int) </li></ul><u...
高阶函数的应用   -  函数式 3D 建模 <ul><li>参数化曲面  (R,R) -> (R,R,R) </li></ul><ul><li>隐式曲面和空间区域: (R,R,R) -> R, 通过计算结果的符号来判断是否在区域内 </li>...
Example -  FieldTrip http://www.haskell.org/haskellwiki/FieldTrip <ul><li>talk is cheap </li></ul><ul><li>show me the runn...
Example -  FieldTrip <ul><li>circle :: Curve2 </li></ul><ul><li>semiCircle :: Curve2 </li></ul><ul><li>--  让曲线绕着 Z 轴转一圈 </...
Example -  函数式 3D 建模 <ul><li>采用类似的思想,我们还能描述更复杂的 3D 场景 </li></ul>
Algebraic Data Type <ul><li>data 是关键字,用来定义新的数据类型,可以带零或多个类型参数 </li></ul><ul><li>每个新类型有一或多个 constructor 用来创建该类型的值 </li></ul>...
Algebraic Data Type <ul><li>用具体的参数类型来具化 Maybe : Maybe Int </li></ul><ul><ul><li>Just 20 </li></ul></ul><ul><ul><li>Nothing...
Pattern Matching <ul><li>constructor 可以作为函数来创建值 </li></ul><ul><li>也可以用在 pattern 里萃取被包裹的值 </li></ul><ul><li>tree =  </li></...
某种多态的函数 <ul><li>试着定义这样一个函数,它判断某个值是否在 list 里 </li></ul><ul><li>作为懒惰的程序员,我们当然希望函数的定义只写一次 </li></ul><ul><li>问题来了,我们怎么样描述这样一种数...
Type Classes <ul><li>class  Eq a where </li></ul><ul><li>(==) :: a -> a -> Bool </li></ul><ul><li>elem :: Eq a => a->[a]->...
Instance of Type Classes <ul><li>instance  Eq (Maybe a) where </li></ul><ul><li>Just v1 == Just v2 = v1 == v2 </li></ul><u...
Lazy Evaluation <ul><li>a = [1..] -- infinite list </li></ul><ul><li>take 3 a -- [1,2,3] </li></ul>
Purity <ul><li>好吧, Functional 我早就明白了, </li></ul><ul><li>可“纯粹”是什么? </li></ul>
Purity <ul><li>variable 一旦和某个数据绑定了就不可再修改了, </li></ul><ul><li>所以它不再是可变的量,而仅仅是一个不可变的值的名 </li></ul><ul><li>字。 </li></ul><ul><...
Purity <ul><li>函数不会有 side effect ,不会对数据做破坏性的修改,不会 </li></ul><ul><li>改变外部世界的状态,它的输出只依赖它的输入,任何时刻, </li></ul><ul><li>给定同样的输入,...
Referential Transparent <ul><li>能用 2 * f(x)  来替换 f(x) + f(x) 吗? </li></ul><ul><li>int y = 10; </li></ul><ul><li>int f(int ...
能用来做事吗? <ul><li>如果连状态都不能改变,那它有个鸟用! </li></ul><ul><li>不要误会,所谓不能改变状态指的是函数求值的时候不允许改变状态,并不意味着程序运行的时候不能改变状态 </li></ul><ul><li>这...
IO Action <ul><li>IO () 是一种 IO 动作,它是普通的 first-class 的数据,如果它被执行就会做某些输入输出操作, IO 动作只能被其它的 IO 动作嵌套, main 是最外层的 IO 动作,也是程序的入口点 ...
Monad <ul><li>所有会引发状态改变的动作(包括 IO Action )都是一种 Monad 。 </li></ul><ul><li>听起来象是 Monster !  </li></ul><ul><li>Haskell 最大的错误是把...
Monad <ul><li>class Monad m where  </li></ul><ul><li>bind  :: m a -> (a -> m b) -> m b </li></ul><ul><li>inject  :: a ->  ...
Example -  函数式音乐编程 <ul><li>创建一种 DSL ,既能表达高层的音乐结构,也能表达底层的声音信号处理。 </li></ul><ul><li>什么特性特别有助于在 Haskell 里创建 EDSL ? </li></ul>...
Example -  函数式音乐编程 , Hommage Haskell Offline Music Manipulation And Generation EDSL http://substitut-fuer-feinmotorik.net/...
<ul><li>并发与并行 </li></ul>
线程 <ul><li>非操作系统线程,极为轻量 </li></ul><ul><li>你可以成千上万地随便创建 </li></ul><ul><li>forkIO :: IO () -> IO ThreadId </li></ul><ul><li>...
Shared Mutable State Concurrency <ul><li>Race conditions due to forgotten locks </li></ul><ul><li>Deadlocks resulting from...
Software Transactional Memory(STM) <ul><li>一组动作可以作为一个 transaction 被执行以保证原子性,一旦线程进入这个原子块,那么其它的线程在该原子块退出之前无法看到其做的修改,同样,这个线程在...
STM Sample <ul><li>import Control.Concurrent.STM </li></ul><ul><li>type Bal =  TVar  Float </li></ul><ul><li>transfer::Flo...
事务执行 <ul><li>transferTest = do </li></ul><ul><li>alice <-  newTVar  12 </li></ul><ul><li>bob <-  newTVar  4 </li></ul><ul>...
Composable STM <ul><li>orElse :: STM a -> STM a -> STM a </li></ul><ul><li>retry :: STM a </li></ul><ul><li>throwSTM :: ex...
让我们并行地工作吧! <ul><li>--  一个顺序程序 </li></ul><ul><li>sort :: (Ord a) => [a] -> [a] </li></ul><ul><li>sort (x:xs) = lesser ++ x:...
让我们并行地工作吧! <ul><li>--  一个并行程序 </li></ul><ul><li>import Control.Parallel (par, pseq) </li></ul><ul><li>parSort :: (Ord a) =...
并行 FP 并不遥远 <ul><li>Map-(Filt)-Reduce(Haskell 里叫 Fold) ,是 FP 里司空见惯的 pattern </li></ul><ul><li>Mapper 、 Filter 和 Reducer 在处理...
并行 FP 并不遥远 <ul><li>所以, Google 将此 pattern 发扬光大,用于大规模并行化数据处理,打造了经典的 Map/Reduce 编程框架(尽管采用了 C++ 来实现),和 Google File System 、 Bi...
用 Haskell 做一个简单的 MapReduce 框架 <ul><li>import Control.Parallel.Strategies </li></ul><ul><li>mapReduce :: </li></ul><ul><li>...
异构并行计算 <ul><li>绝大多数的个人电脑中都有一个强劲的并行处理器:显卡中的 GPU ! </li></ul><ul><li>没有道理限制代码只能在 CPU 上奔跑 </li></ul><ul><li>对 GPU 编程: Shader ...
Example -  函数式 GPU 编程 <ul><li>GPipe </li></ul><ul><li>http://www.haskell.org/haskellwiki/GPipe </li></ul>
Parser Combinator <ul><li>每个程序员或多或少都会干点 parse 的工作 </li></ul><ul><li>所谓 parse ,其实就是将一段无结构的数据(通常是线性的字符串、二进制流)转换成定义良好的结构化数据 <...
Example - Parser Combinator for JavaScript <ul><li>parser 是这样一个函数 :String -> Result </li></ul><ul><li>Result 是一个对象,包含 3 个字...
这些 EDSL 的共同点 <ul><li>把你对特定问题的“描述”送进头等舱,成为 first-class 的 </li></ul><ul><li>结构化数据,为其选择合适的 combinator ,使之不断组合产生 </li></ul><ul...
性能 <ul><li>天下武功,唯快不破  -- 火云邪神 </li></ul><ul><li>The Computer Language Benchmarks Game   </li></ul><ul><ul><li>http://shoot...
真有人用它来做产品吗?
都有谁呢?
本次分享的起因 <ul><li>前台技术中心要成立兴趣小组学习一门新语言,在比较过多门语言后,选择了 Haskell </li></ul><ul><li>FP 正在深刻地影响工业界。比如 Scala ,它的目的是将 Haskell 的思考方式带...
关于我 <ul><li>邓际锋 </li></ul><ul><li>[email_address] </li></ul><ul><li>http://blog.csdn.net/soloist </li></ul><ul><li>个人研究兴趣包...
<ul><li>谢谢! </li></ul>
Upcoming SlideShare
Loading in …5
×

Hi Haskell

2,973 views

Published on

Haskell语言的概览性介绍,内容有:
若干语言特性(是什么让Haskell如此独特?):Lambda,Curry,
Algebraic Data Type,Type Class,
Purity,Lazy Evaluation;
对并行与并发的支持;
若干有启发性的例子以及性能问题;
Haskell在工业界的应用;

Published in: Education, Technology
1 Comment
5 Likes
Statistics
Notes
  • this is what i need
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
2,973
On SlideShare
0
From Embeds
0
Number of Embeds
7
Actions
Shares
0
Downloads
68
Comments
1
Likes
5
Embeds 0
No embeds

No notes for slide

Hi Haskell

  1. 1. Hi Haskell
  2. 2. <ul><li>“ A language that doesn’t effect how you think about programming is not worth learning” </li></ul>Alan Perlis
  3. 3. 提纲 <ul><li>概述 </li></ul><ul><li>若干语言特性(是什么让 Haskell 如此独特?) </li></ul><ul><ul><li>Lambda , Curry </li></ul></ul><ul><ul><li>Algebraic Data Type , Type Class </li></ul></ul><ul><ul><li>Purity, Lazy Evaluation </li></ul></ul><ul><li>也许来个中场休息? (optional) </li></ul><ul><li>对并行与并发的支持 </li></ul><ul><li>若干例子以及性能问题 </li></ul><ul><li>Haskell 在工业界的应用 </li></ul><ul><li>总结 </li></ul>
  4. 4. 编程范式 (Programming Paradigm) <ul><li>令一门编程语言区别于其它语言的根本在于它所提供的编程范式 </li></ul><ul><li>编程范式指的是编程活动中所遵循的根本风格。它包括选取何种基本元素来构成程序(比如对象,函数,变量,约束条件等等)以及用何种方式来表达计算过程(比如赋值、表达式求值,数据流等等)。 -- 维基百科 </li></ul>
  5. 5. 你知道并用过多少种编程范式? <ul><li>Imperative </li></ul><ul><li>Declarative </li></ul><ul><li>Object-Oriented </li></ul><ul><li>Aspect-Oriented </li></ul><ul><li>Event-Driven </li></ul><ul><li>Functional </li></ul><ul><li>Generic </li></ul><ul><li>Logic </li></ul><ul><li>Concurrent </li></ul>
  6. 6. 其实还有更多!
  7. 7. Functional Programming <ul><li>在 FP 这种编程范式里,计算是通过对函数的求值 (evaluation) 来组织的,它尽量避免涉及状态与可变 (mutable) 数据。 FP 强调的是函数的施用 (application) ,与之相对的命令式编程强调的则是状态的改变。 </li></ul><ul><li>几乎所有的主流语言都是偏向命令式的。 </li></ul>
  8. 8. <ul><li>简单来说 ,Haskell 是一门通用的、静态强类型的、 </li></ul><ul><li>pure (该叫纯粹还是纯洁呢? ) 的、函数式编程语言。 </li></ul><ul><li>它提供的最基本的编程范式是 FP ,另外还能支持其它多种范式。 </li></ul>
  9. 9. Lambda 表达式(匿名函数) <ul><li>(x y->x*10+y) 5 9 </li></ul><ul><li>--59 </li></ul><ul><li>大部分时候可以象动态语 </li></ul><ul><li>言那样不写类型声明,编 </li></ul><ul><li>译器会尽全力推导出表达 </li></ul><ul><li>式的类型,如果推导失败, </li></ul><ul><li>它会抱怨的 </li></ul><ul><li>//JavaScript </li></ul><ul><li>(function (x,y){ </li></ul><ul><li>return x*10 + y </li></ul><ul><li>})(5,9) </li></ul>
  10. 10. First-Class Function & High Order Function <ul><li>函数是语言中的一等公民,意味着它享有和 Int 、 Float 这些基本类型一样的公民权利: </li></ul><ul><ul><li>函数本身可以作为参数传递 </li></ul></ul><ul><ul><li>函数本身可以作为返回值 </li></ul></ul><ul><ul><li>函数本身可以作为复合类型数据的一部分 </li></ul></ul><ul><li>高阶函数是这样一个东东: </li></ul><ul><ul><li>或者它的参数是另外的函数 </li></ul></ul><ul><ul><li>或者它的返回值是一个函数 </li></ul></ul>
  11. 11. Currying(Partial Application)&High Order <ul><li>-- f::Int->Int->Int </li></ul><ul><li>-- f::Int->(Int->Int) </li></ul><ul><li>f x y=x*10 + y </li></ul><ul><li>f5 = f 5 </li></ul><ul><li>f7 = f 7 </li></ul><ul><li>f5 9 -- 59 </li></ul><ul><li>f5 1 -- 51 </li></ul><ul><li>f7 9 -- 79 </li></ul><ul><li>f7 1 -- 71 </li></ul><ul><li>//JavaScript </li></ul><ul><li>function f(x) { </li></ul><ul><li>return function(y) { </li></ul><ul><li>return x * 10 + y </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>f5 = f(5) </li></ul><ul><li>f7 = f(7) </li></ul><ul><li>f5(9) // 59 </li></ul><ul><li>f7(1) // 71 </li></ul>
  12. 12. 高阶函数的应用 - 函数式 3D 建模 <ul><li>参数化曲面 (R,R) -> (R,R,R) </li></ul><ul><li>隐式曲面和空间区域: (R,R,R) -> R, 通过计算结果的符号来判断是否在区域内 </li></ul><ul><li>高度图: (R,R) -> R </li></ul><ul><li>2D 曲线 : R -> (R,R) </li></ul><ul><li>变换 : (R,R,R) -> (R,R,R) </li></ul><ul><li>图像 : (R,R) -> Color </li></ul>
  13. 13. Example - FieldTrip http://www.haskell.org/haskellwiki/FieldTrip <ul><li>talk is cheap </li></ul><ul><li>show me the running code </li></ul>
  14. 14. Example - FieldTrip <ul><li>circle :: Curve2 </li></ul><ul><li>semiCircle :: Curve2 </li></ul><ul><li>-- 让曲线绕着 Z 轴转一圈 </li></ul><ul><li>revolve :: Curve2 -> ParamSurf </li></ul><ul><li>torus :: R -> R -> ParamSurf </li></ul><ul><li>-- sr :内径 cr: 截面半径 </li></ul><ul><li>torus sr cr = revolve (const (sr,0) ^+^ const cr *^ circle) </li></ul><ul><li>sphere = revolve semiCircle </li></ul>
  15. 15. Example - 函数式 3D 建模 <ul><li>采用类似的思想,我们还能描述更复杂的 3D 场景 </li></ul>
  16. 16. Algebraic Data Type <ul><li>data 是关键字,用来定义新的数据类型,可以带零或多个类型参数 </li></ul><ul><li>每个新类型有一或多个 constructor 用来创建该类型的值 </li></ul><ul><li>每个 constructor 有零或多个参数,参数的类型可以是类型参数指定的类型以及任意可见类型 </li></ul><ul><li>data Maybe a = </li></ul><ul><li>Just a </li></ul><ul><li>| Nothing </li></ul><ul><li>data Tree a = </li></ul><ul><li>Empty </li></ul><ul><li>| Leaf a </li></ul><ul><li>| Node (Tree a)(Tree a) </li></ul>递归的类型定义 带一个参数的 Constructor 不带参数的 Constructor
  17. 17. Algebraic Data Type <ul><li>用具体的参数类型来具化 Maybe : Maybe Int </li></ul><ul><ul><li>Just 20 </li></ul></ul><ul><ul><li>Nothing </li></ul></ul><ul><li>当我们拿到一个 Maybe Int 的值,如何知道它包裹的整型数到底是多少? </li></ul>
  18. 18. Pattern Matching <ul><li>constructor 可以作为函数来创建值 </li></ul><ul><li>也可以用在 pattern 里萃取被包裹的值 </li></ul><ul><li>tree = </li></ul><ul><li>Node (Leaf 4) (Node Empty (Leaf 5)) </li></ul><ul><li>accum Empty = 0 </li></ul><ul><li>accum (Leaf a) = a </li></ul><ul><li>accum (Node left right) = (accum left) + (accum right) </li></ul><ul><li>accum tree -- 9 </li></ul>
  19. 19. 某种多态的函数 <ul><li>试着定义这样一个函数,它判断某个值是否在 list 里 </li></ul><ul><li>作为懒惰的程序员,我们当然希望函数的定义只写一次 </li></ul><ul><li>问题来了,我们怎么样描述这样一种数据类型,它的值是可以进行相等性测试的? </li></ul>
  20. 20. Type Classes <ul><li>class Eq a where </li></ul><ul><li>(==) :: a -> a -> Bool </li></ul><ul><li>elem :: Eq a => a->[a]->Bool </li></ul><ul><li>elem k (x:xs) </li></ul><ul><li>| k == x = True </li></ul><ul><li>| otherwise = elem k xs </li></ul><ul><li>elem k [] = False </li></ul>OO 的 class
  21. 21. Instance of Type Classes <ul><li>instance Eq (Maybe a) where </li></ul><ul><li>Just v1 == Just v2 = v1 == v2 </li></ul><ul><li>Nothing == Nothing = True </li></ul><ul><li>_ == _ = False </li></ul>
  22. 22. Lazy Evaluation <ul><li>a = [1..] -- infinite list </li></ul><ul><li>take 3 a -- [1,2,3] </li></ul>
  23. 23. Purity <ul><li>好吧, Functional 我早就明白了, </li></ul><ul><li>可“纯粹”是什么? </li></ul>
  24. 24. Purity <ul><li>variable 一旦和某个数据绑定了就不可再修改了, </li></ul><ul><li>所以它不再是可变的量,而仅仅是一个不可变的值的名 </li></ul><ul><li>字。 </li></ul><ul><li>a = 3 </li></ul><ul><li>a = 19 </li></ul>
  25. 25. Purity <ul><li>函数不会有 side effect ,不会对数据做破坏性的修改,不会 </li></ul><ul><li>改变外部世界的状态,它的输出只依赖它的输入,任何时刻, </li></ul><ul><li>给定同样的输入,一定得到同样的输出。数学中的函数从来就具 </li></ul><ul><li>有这样的性质,可在大多数编程语言中这种美好的性质却被毁了。 </li></ul>
  26. 26. Referential Transparent <ul><li>能用 2 * f(x) 来替换 f(x) + f(x) 吗? </li></ul><ul><li>int y = 10; </li></ul><ul><li>int f(int i) </li></ul><ul><li>{ </li></ul><ul><li>return i + y++; </li></ul><ul><li>} </li></ul><ul><li>f(5) + f(5); // 15 + 16 = 31 </li></ul><ul><li>2 * f(5); // 2 * 15 = 30 </li></ul>
  27. 27. 能用来做事吗? <ul><li>如果连状态都不能改变,那它有个鸟用! </li></ul><ul><li>不要误会,所谓不能改变状态指的是函数求值的时候不允许改变状态,并不意味着程序运行的时候不能改变状态 </li></ul><ul><li>这是什么意思? </li></ul>
  28. 28. IO Action <ul><li>IO () 是一种 IO 动作,它是普通的 first-class 的数据,如果它被执行就会做某些输入输出操作, IO 动作只能被其它的 IO 动作嵌套, main 是最外层的 IO 动作,也是程序的入口点 </li></ul><ul><li>一个 IO 动作在创建的时候并不会执行,只有在嵌套它的外层动作被执行时才会跟着执行,所以执行和函数求值是不同的 </li></ul><ul><li>所有的 IO 动作都是由运行程序开始执行 main 而引发的 </li></ul>--putStrLn :: String -> IO () --main :: IO () main = putStrLn &quot;Hi Haskell!&quot;
  29. 29. Monad <ul><li>所有会引发状态改变的动作(包括 IO Action )都是一种 Monad 。 </li></ul><ul><li>听起来象是 Monster ! </li></ul><ul><li>Haskell 最大的错误是把 Monad 叫作 Monad !或许应该喊它 &quot;warm fuzzy thing&quot; ( 暖毛毛 )! </li></ul><ul><ul><li>-- Simon Peyton Jones , Haskell 设计者之一 </li></ul></ul>
  30. 30. Monad <ul><li>class Monad m where </li></ul><ul><li>bind :: m a -> (a -> m b) -> m b </li></ul><ul><li>inject :: a -> m a </li></ul>Monad m a bind inject a (a -> m b)
  31. 31. Example - 函数式音乐编程 <ul><li>创建一种 DSL ,既能表达高层的音乐结构,也能表达底层的声音信号处理。 </li></ul><ul><li>什么特性特别有助于在 Haskell 里创建 EDSL ? </li></ul><ul><ul><li>纯洁的函数和高阶函数 </li></ul></ul><ul><ul><li>Algebraic Data Type </li></ul></ul><ul><ul><li>强类型检查 </li></ul></ul><ul><ul><li>惰性求值 </li></ul></ul><ul><ul><li>二元函数的中缀写法 </li></ul></ul>
  32. 32. Example - 函数式音乐编程 , Hommage Haskell Offline Music Manipulation And Generation EDSL http://substitut-fuer-feinmotorik.net/projects/haskellommage
  33. 33. <ul><li>并发与并行 </li></ul>
  34. 34. 线程 <ul><li>非操作系统线程,极为轻量 </li></ul><ul><li>你可以成千上万地随便创建 </li></ul><ul><li>forkIO :: IO () -> IO ThreadId </li></ul><ul><li>forkIO (writeFile &quot;temp.txt&quot; &quot;haskell thread&quot;) </li></ul>
  35. 35. Shared Mutable State Concurrency <ul><li>Race conditions due to forgotten locks </li></ul><ul><li>Deadlocks resulting from inconsistent lock ordering </li></ul><ul><li>Corruption caused by uncaught exceptions </li></ul><ul><li>Lost wakeups induced by omitted notifications </li></ul>
  36. 36. Software Transactional Memory(STM) <ul><li>一组动作可以作为一个 transaction 被执行以保证原子性,一旦线程进入这个原子块,那么其它的线程在该原子块退出之前无法看到其做的修改,同样,这个线程在此期间也无法看到别人做的修改 </li></ul><ul><li>在退出原子块的时候,结果要么是 a 要么是 b </li></ul><ul><ul><li>transaction 成功执行,其它线程可以立刻看见它所做的状态修改 </li></ul></ul><ul><ul><li>transaction 执行失败,所有的修改被抛弃 </li></ul></ul>
  37. 37. STM Sample <ul><li>import Control.Concurrent.STM </li></ul><ul><li>type Bal = TVar Float </li></ul><ul><li>transfer::Float->Bal->Bal->STM () </li></ul><ul><li>transfer qty fromBal toBal = do </li></ul><ul><li>fromQty <- readTVar fromBal </li></ul><ul><li>toQty <- readTVar toBal </li></ul><ul><li>writeTVar fromBal (fromQty - qty) </li></ul><ul><li>writeTVar toBal (toQty + qty) </li></ul>
  38. 38. 事务执行 <ul><li>transferTest = do </li></ul><ul><li>alice <- newTVar 12 </li></ul><ul><li>bob <- newTVar 4 </li></ul><ul><li>transfer 3 alice bob </li></ul><ul><li>-- atomically:: STM a -> IO a </li></ul><ul><li>main = atomically transferTest </li></ul>
  39. 39. Composable STM <ul><li>orElse :: STM a -> STM a -> STM a </li></ul><ul><li>retry :: STM a </li></ul><ul><li>throwSTM :: exception -> STM a </li></ul><ul><li>catchSTM :: STM a -> (exception->STM a) -> STM a </li></ul><ul><li>instance Monad STM </li></ul><ul><li>complexAction = action1 `orElse` action2 </li></ul><ul><li>main = atomically complexAction </li></ul>
  40. 40. 让我们并行地工作吧! <ul><li>-- 一个顺序程序 </li></ul><ul><li>sort :: (Ord a) => [a] -> [a] </li></ul><ul><li>sort (x:xs) = lesser ++ x:greater </li></ul><ul><li>where lesser = sort [y | y <- xs, y < x] </li></ul><ul><li>greater = sort [y | y <- xs, y >= x] </li></ul><ul><li>sort _ = [] </li></ul>
  41. 41. 让我们并行地工作吧! <ul><li>-- 一个并行程序 </li></ul><ul><li>import Control.Parallel (par, pseq) </li></ul><ul><li>parSort :: (Ord a) => [a] -> [a] </li></ul><ul><li>parSort (x:xs) = force greater `par` </li></ul><ul><li>( force lesser `pseq` (lesser ++ x:greater)) </li></ul><ul><li>where lesser = parSort [y | y <- xs, y < x] </li></ul><ul><li>greater = parSort [y | y <- xs, y >= x] </li></ul><ul><li>parSort _ = [] </li></ul>
  42. 42. 并行 FP 并不遥远 <ul><li>Map-(Filt)-Reduce(Haskell 里叫 Fold) ,是 FP 里司空见惯的 pattern </li></ul><ul><li>Mapper 、 Filter 和 Reducer 在处理某个数据集合时并不依赖于其它的数据集合,天生就适合并行化 </li></ul>
  43. 43. 并行 FP 并不遥远 <ul><li>所以, Google 将此 pattern 发扬光大,用于大规模并行化数据处理,打造了经典的 Map/Reduce 编程框架(尽管采用了 C++ 来实现),和 Google File System 、 BigTable 一道成为 Google 搜索技术的三大基石 </li></ul><ul><li>Hadoop, Map/Reduce 的开源实现,为无数互联网公司所使用 </li></ul><ul><li>其实我们每天都在享受着 FP 提供的服务 </li></ul>
  44. 44. 用 Haskell 做一个简单的 MapReduce 框架 <ul><li>import Control.Parallel.Strategies </li></ul><ul><li>mapReduce :: </li></ul><ul><li>Strategy b -- evaluation strategy for mapping </li></ul><ul><li>-> (a -> b) -- map function </li></ul><ul><li>-> Strategy c -- evaluation strategy for reduction </li></ul><ul><li>-> ([b] -> c) -- reduce function </li></ul><ul><li>-> [a] -- list to map over </li></ul><ul><li>-> c </li></ul><ul><li>mapReduce mapStrat mapFunc reduceStrat reduceFunc input </li></ul><ul><li>= mapResult `pseq` reduceResult </li></ul><ul><li>where mapResult = parMap mapStrat mapFunc input </li></ul><ul><li>reduceResult = reduceFunc mapResult `using` reduceStrat </li></ul>
  45. 45. 异构并行计算 <ul><li>绝大多数的个人电脑中都有一个强劲的并行处理器:显卡中的 GPU ! </li></ul><ul><li>没有道理限制代码只能在 CPU 上奔跑 </li></ul><ul><li>对 GPU 编程: Shader 、 CUDA 、 OpenCL </li></ul><ul><li>GPU 的执行模型天生就适合 FP </li></ul><ul><li>GPipe ,一种 EDSL ,也是一种函数式的 GPU 编程模型 , 直接用 Haskell 写 GPU 程序,从而利用 Haskell 的种种迷人特性,运行时动态生成 OpenGL 的 GLSL ,提交给显卡执行 </li></ul>
  46. 46. Example - 函数式 GPU 编程 <ul><li>GPipe </li></ul><ul><li>http://www.haskell.org/haskellwiki/GPipe </li></ul>
  47. 47. Parser Combinator <ul><li>每个程序员或多或少都会干点 parse 的工作 </li></ul><ul><li>所谓 parse ,其实就是将一段无结构的数据(通常是线性的字符串、二进制流)转换成定义良好的结构化数据 </li></ul><ul><li>有许多工具 ( 比如 Lex 、 Yacc 、 Flex 、 Bison 、 Antlr) 自动生成 parse 代码 </li></ul><ul><li>Haskell 社区首先探索了一种独特的方式来构建复杂的 parser ,称为 Parser Combinator 。这种思想纷纷为许多其它语言所借鉴。 </li></ul>
  48. 48. Example - Parser Combinator for JavaScript <ul><li>parser 是这样一个函数 :String -> Result </li></ul><ul><li>Result 是一个对象,包含 3 个字段: </li></ul><ul><ul><li>remaining: 剩下的有待 parse 的字符串 </li></ul></ul><ul><ul><li>matched: 被该 parser 成功 parse 的字符串 </li></ul></ul><ul><ul><li>ast: parse 后生成的抽象语法树 </li></ul></ul><ul><li>有若干预定义的基本的 parser ,比如 </li></ul><ul><ul><li>range(&quot;0&quot;, &quot;9&quot;) </li></ul></ul><ul><ul><li>token(&quot;begin&quot;) </li></ul></ul><ul><li>parser 可以用 combinator 组合起来,得到一个新的 ( 更复杂的 )parser </li></ul><ul><ul><li>repeat1(alternate(sequence(parser1, parser2), parser3)) </li></ul></ul>
  49. 49. 这些 EDSL 的共同点 <ul><li>把你对特定问题的“描述”送进头等舱,成为 first-class 的 </li></ul><ul><li>结构化数据,为其选择合适的 combinator ,使之不断组合产生 </li></ul><ul><li>更复杂的方案,直到能完全描述出最终的程序意图。 </li></ul>
  50. 50. 性能 <ul><li>天下武功,唯快不破 -- 火云邪神 </li></ul><ul><li>The Computer Language Benchmarks Game   </li></ul><ul><ul><li>http://shootout.alioth.debian.org/ </li></ul></ul><ul><ul><li>平均来说, Haskell 的速度是 C 的 1/5 </li></ul></ul><ul><li>眼见为实 —— 2D 水波特效 </li></ul><ul><ul><li>http://blog.csdn.net/soloist/archive/2009/04/09/4060081.aspx </li></ul></ul>
  51. 51. 真有人用它来做产品吗?
  52. 52. 都有谁呢?
  53. 53. 本次分享的起因 <ul><li>前台技术中心要成立兴趣小组学习一门新语言,在比较过多门语言后,选择了 Haskell </li></ul><ul><li>FP 正在深刻地影响工业界。比如 Scala ,它的目的是将 Haskell 的思考方式带给 Java 程序员,已经成为 JVM 上的主流语言,正在成为其上的统治性语言 </li></ul><ul><li>无论你常用的是什么语言,掌握一门 FP 尤其是 Haskell 这样的纯粹的 FP ,都会使你成为更好更好的 programmer </li></ul>
  54. 54. 关于我 <ul><li>邓际锋 </li></ul><ul><li>[email_address] </li></ul><ul><li>http://blog.csdn.net/soloist </li></ul><ul><li>个人研究兴趣包括 </li></ul><ul><li>编程语言的设计与实现 </li></ul><ul><li>交互式艺术及 FP 在该领域的应用 </li></ul><ul><li>如何为儿童和非技术人员开发富有乐趣的创作工具 </li></ul>
  55. 55. <ul><li>谢谢! </li></ul>

×