* [[http://www.yinwang.org/blog-cn/2013/03/31/purely-functional|对函数式语言的误解]]
* [[http://stackoverflow.com/questions/2835801/why-hasnt-functional-programming-taken-over-yet|Why hasn't functional programming taken over yet?]]
* [[http://stackoverflow.com/questions/7875253/what-is-the-purpose-of-a-stack-why-do-we-need-it-msil|What is the purpose of a stack? Why do we need it? (MSIL)]]
* [[http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html|函数式编程入门教程]]
====== Haskell ======
* [[https://github.com/fpinscala/fpinscala/wiki/A-brief-introduction-to-Haskell,-and-why-it-matters|A brief introduction to Haskell, and why it matters]]
* [[http://learnyouahaskell.com/|Learn You a Haskell for Great Good!]]
====== Scheme ======
* [[http://www.yinwang.org/blog-cn/2012/08/01/interpreter|怎样写一个解释器]]
* [[http://yinwang0.lofter.com/post/183ec2_47c086|怎样写一个解释器 (舊版)]]
* [[http://mitpress.mit.edu/sicp/|Structure and Interpretation of Computer Programs]]
* [[http://xuanji.appspot.com/isicp/|Structure and Interpretation of Computer Programs Interactive Version]]
* [[wp>Scheme (programming language)|Scheme]]
* [[http://racket-lang.org/|Racket]]
====== Scala ======
* [[http://www.artima.com/pins1ed/|Programming in Scala]]
* [[http://www.artima.com/pins1ed/builtin-control-structures.html|Chapter 7 Built-in Control Structures]]
* [[http://www.artima.com/pins1ed/for-expressions-revisited.html|Chapter 23 For Expressions Revisited]]
* for 表達式 (和一般程式語言為 for 述句不同,for 表達式有返回值) 是 map、flatMap 和 filter 的語法糖,較容易讓人理解其意圖。
// definition、filter 和 yield 可選。yield 使得 for 表達式有返回值。
// 此例中,返回由 n 組成的列表 (list)。
for {
p <- persons // a generator
n = p.name // a definition
if (n startsWith "To") // a filter
} yield n
* [[http://www.artima.com/pins1ed/working-with-lists.html|Chapter 16 Working with Lists]]
* 所謂的高階函數 (higher-order function),就是其輸入或返回的也是函數 (first-order function)。
* [[http://www.artima.com/pins1ed/working-with-lists.html#i364816247-1|16.7 Higher-order methods on class List]]
* [[http://www.brunton-spall.co.uk/post/2011/12/02/map-map-and-flatmap-in-scala/|Map, Map and flatMap in Scala]]
* flatMap: 先 Map,再 flat。Map(f) 對列表中每一個元素應用時,會得到列表 List[T],最終得到 List[List[T]]。flat 把 List[List[T]] 中的每個一元素 List[T] 打散並加以合併,最終形成單一個列表 List[T]。
* [[http://daily-scala.blogspot.se/2010/05/zipwithindex.html|zipWithIndex]]
* zipWithIndex:
scala> val abcde = List('a', 'b', 'c', 'd', 'e')
abcde: List[Char] = List(a, b, c, d, e)
scala> abcde.zipWithIndex
res15: List[(Char, Int)] = List((a,0), (b,1), (c,2), (d,3),
(e,4))
* [[http://www.artima.com/pins1ed/type-parameterization.html|Chapter 19 Type Parameterization]]
* 類型參數化 (即 C++ 的模板)
* S <: T
* S 是 T 的子類 (subclass)。
* S <: T 是否意味著 List[S] <: List[T],是協變 (covariant,協同變動) 和逆協變所要解決的問題。預設為非協變 ( nonvariant),即 List[S] 和 List[T] 之間不存在任何繼承關係。
* [[http://www.artima.com/pins1ed/implicit-conversions-and-parameters.html|Chapter 21 Implicit Conversions and Parameters]]
* [[http://www.artima.com/pins1ed/implicit-conversions-and-parameters.html#21.5|21.5 Implicit parameters]]
* [[http://daily-scala.blogspot.se/2010/04/implicit-parameters.html|Implicit Parameters]]
* An implicit parameter is a parameter to method or constructor that is marked as implicit. This means that if a parameter value is not supplied then the compiler will search for an "implicit" value defined within scope (according to resolution rules.) Implicit parameter resolution rules will be discussed soon.
* One important restriction is that there can only be a single implicit keyword per method. It must be at the start of a parameter list (which also makes all values of that parameter list be implicit). I further understand that only the last parameter list may be implicit.
* [[https://www.artima.com/pins1ed/combinator-parsing.html|Chapter 31 Combinator Parsing]]
* [[http://bitwalker.org/posts/2013-08-10-learn-by-example-scala-parser-combinators/|Learn by Example: Scala Parser Combinators]]
* [[http://henkelmann.eu/2011/01/13/an_introduction_to_scala_parser_combinators|An Introduction To Scala Parser Combinators - Part 1: Parser Basics]]
* [[http://henkelmann.eu/2011/01/28/an_introduction_to_scala_parser_combinators-part_2_literal_expressions|An Introduction To Scala Parser Combinators - Part 2: Parsing Literal Expressions]]
* [[http://henkelmann.eu/2011/01/29/an_introduction_to_scala_parser_combinators-part_3_unit_tests|An Introduction To Scala Parser Combinators - Part 3: Writing unit tests for parsers]]
* [[https://github.com/scala/scala-parser-combinators|Scala Standard Parser Combinator Library]]
* Lexical 是特殊的 parser,取消 Inherited 中的 Tokens、Scanners 和 Parsers,可以看到 Lexical 自己定義的成員。
* 點擊 Type Members 中的 Parser,可以查看 Parser 提供的操作符 (如: ^^^)。
* 解析器 (parser) 組和子/連結符 (combinator): 解析器可以視作為一個函數,輸入為字串,輸出為一資料結構。透過組合子,Scala 可以將多個解析器合併成單一個解析器。
* Parser[T]: Input => ParseResult[T]
* T: parse 之後的結果。
* Input: 可以是單純的字元串流 (type Elem = Char) 或是從 lexer 傳回的 (Reader[Elem])。
* ParseResult[T]: 可以是 Success(result: T, in: Input),或是 Failure(errmsg: String, in: Input)。
* | combinator 會看到 call-by-name (a: => A) 的應用。
* | combinator 可以看做是函數,call-by-name 代表該參數只有在被調用到時才會執行。與其相對,一般我們看到參數傳遞的方式都是 call-by-value,即參數傳入函數之前,就會被求值 (執行)。
* [[http://www.scala-lang.org/index.html|The Scala Programming Language]]
* [[https://www.jetbrains.com/idea/|IntelliJ IDEA]]
* [[http://scala-ide.org/|Scala IDE for Eclipse]]
* [[http://stackoverflow.com/questions/14796390/could-not-find-implicit-value-for-evidence-parameter-of-type-scala-reflect-class|Could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T]]]
* 無法找到型別為 scala.reflect.ClassManifest[T] 的 implicit 參數,可以透過 import 引入正確的 implicit 參數解決。
* [[http://stackoverflow.com/questions/25222989/erasure-elimination-in-scala-non-variable-type-argument-is-unchecked-since-it|Erasure elimination in scala : non-variable type argument is unchecked since it is eliminated by erasure]]
* 函式欲根據容器內的元素類型,調用對映的處理函式。
* 改由 caller 根據容器內的元素類型,傳給 callee 對映的處理函式 (callee(f)(xs: List[T]))。
===== Functional Programming in Scala =====
* [[https://www.manning.com/books/functional-programming-in-scala|Functional Programming in Scala]]
* Ch.1
* [[wp>Referential transparency]]
* 程式中的表達式可以被其運算結果取代,不影響程式語義。
* Pure function
* x 滿足 referential transparency,f(x) 亦滿足 referential transparency,則稱函式 f 為 pure。
* Ch.3
* [[wp>Algebraic data type]]
* List 是一種代數資料型別,本身從其它 ADT 建構而成,也可以用來建構其它 ADT。
* Ch.4
* 例外不滿足 referential transparency。Option 和 Either 是較為推薦的錯誤處理方式。例外只有在程序無法合理進行下去才被丟出。
* Option 可以想成是最多只有包含一個元素的 List,None 對應 Nil。
* 一般函式透過 lifting 可以處理 Option。
// (x: Option[A]) => x map f 可以寫成 _ map f
def lift[A, B](f: A => B): Option[A] => Option[B] = (x: Option[A]) => x map f
val absO: Option[Double] => Option[Double] = lift(math.abs)
// 注意! 用 map/flatMap 實現不容易閱讀。把 Option 當作 List,用 for-comprehension 實現。
def map2[A, B, C](a: Option[A], b: Option[B])(f: (A, B) => C): Option[C] =
for {
aa <- a
bb <- b
} yield f(aa, bb)
* [[http://softwareengineering.stackexchange.com/questions/255696/what-is-a-lifted-representation|What is a “lifted representation”?]]
* xs map f,f 返回 Option。我們希望若 xs 任一元素 apply f 返回 None,則 xs map f 返回 None。
def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] =
a match {
case Nil => Some(Nil)
case h::t => map2(f(h), traverse(t)(f))(_ :: _)
}
* [[http://stackoverflow.com/questions/26602611/how-to-understand-traverse-traverseu-and-traversem|How to understand traverse, traverseU and traverseM]]
* Either 比 Option 對錯誤可以帶有更多資訊,而不只是返回 None。Right 代表正確,Left 代表錯誤。
* 我們可以將 side-effect 包裝成一般 value 返回加以處理。Monad 就是此種概念下的產物。
* Ch.5
* [[https://github.com/fpinscala/fpinscala/wiki/Chapter-5:-Strictness-and-laziness|Chapter 5: Strictness and laziness]]
* 一個函式稱為 strict,代表在被調用之前,其參數均被求值 (所有參數均為 call-by-value)。我們在一般編程語言中所見到的函式皆為 strict。
* 一個函式若有 call-by-name 參數,即為 non-strict (not strict)。
// cond - call by value
// onTrue, onFalse - call by name
def if2[A](cond: Boolean, onTrue: => A, onFalse: => A): A =
if (cond) onTrue else onFalse // onTrue 和 onFalse 在傳入 if2 時不會被求值,此時才會根據 cond 決定誰被求值。
def if2[A](cond: Boolean, onTrue: () => A, onFalse: () => A): A =
if (cond) onTrue() else onFalse() // 上面代碼是此版本的語法糖。onTrue 和 onFalse 分別是 lamda function。
* [[http://stackoverflow.com/questions/13337338/call-by-name-vs-call-by-value-in-scala-clarification-needed|Call by name vs call by value in Scala, clarification needed]]
* [[http://alvinalexander.com/source-code/scala/simple-scala-call-name-example|A simple Scala call-by-name example]]
* 未被求值的表達式 (onTrue() 和 onFalse()) 又被稱為 [[wp>Thunk]]。
* call-by-name 的參數如果有副作用,必須要注意該副作用可能會執行多次。
def maybeTwice(b: Boolean, i: => Int) =
if (b) i + i else 0 // i 被引用兩次,由於 i 是 call-by-name,代表 i 會被求值兩次。
val x = maybeTwice(true, { println("hi"); 1 + 41 }) // 印出兩次 "hi",x = 84。
def maybeTwice(b: Boolean, i: => Int) = {
lazy val j = i // j 第一次被引用,會對 i 求值,並將該值 cache 起來; 後續引用 j 不再對 i 求值。
if (b) j + j else 0 // i 被引用兩次,由於 i 是 call-by-name,代表 i 會被求值兩次。
val x = maybeTwice(true, { println("hi"); 1 + 41 }) // 印出一次 "hi",x = 84。
* [[http://alvinalexander.com/scala/how-to-use-stream-class-lazy-list-scala-cookbook|How to use the Scala Stream class, a lazy version of List]]
* Stream 類似 List。差別在於對其做 map 或是其它運算時,Stream 只會在 caller 需要時,對其中元素進行運算; 而 List 是對其中所有元素一次進行運算。
scala> (1 to 5).toList
res10: List[Int] = List(1, 2, 3, 4, 5) // list 中所有元素立刻被求值。
scala> (1 to 5).toStream
res11: scala.collection.immutable.Stream[Int] = Stream(1, ?) // ? 代表剩下部分未被求值。
* [[wp>Separation of concerns]]。將代碼視作為資料在程序中傳遞,在適當時候可以調用。匿名函式或是 Option 都是此種概念的應用。[[wp>Lazy evaluation]] 讓我們可以將表達式的描述和求值加以分開,只有在需要時才對表達式求值。
* [[http://weblog.raganwald.com/2007/03/why-why-functional-programming-matters.html|Why Why Functional Programming Matters Matters]]
* Ch.6
* 為保持 referential transparency,把 side effect 或是 state 作為返回值。
===== Scalaz =====
* [[https://github.com/scalaz/scalaz|Scalaz]]
* [[http://stackoverflow.com/questions/4863671/good-scalaz-introduction/12391259|Good scalaz introduction]]
* [[http://eed3si9n.com/learning-scalaz/|learning Scalaz]]
* [[https://hseeberger.wordpress.com/2010/11/25/introduction-to-category-theory-in-scala/|Introduction to Category Theory in Scala]]
* [[http://stackoverflow.com/questions/16526282/use-scalaz-in-console-repl-without-creating-a-project|Use scalaz in console repl without creating a project]]
*
$ sbt
set scalaVersion := "2.12.1"
set libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.2.9"
set initialCommands += "import scalaz._, Scalaz._"
session save
console
*
# 下載 scalaz-core_2.12-7.2.9.jar
$ scala -cp scalaz-core_2.12-7.2.9.jar
===== ScalaTest =====
* [[http://www.scalatest.org/|ScalaTest]]
* [[http://www.scalatest.org/quick_start|ScalaTest quick start]]
====== 術語 ======
* [[wp>Lambda calculus]]
* [[wp>S-expression]]
* [[wp>Closure (computer programming)|Closure]]
* [[wp>Monad (functional programming)|Monad]]
* [[http://yinwang0.lofter.com/post/183ec2_b1afb9|为什么说面向对象编程和函数式编程都有问题]]
* [[https://www.youtube.com/watch?v=ZhuHCtR3xq8|Brian Beckman: Don't fear the Monad]]
* [[http://mdjnewman.me/2013/10/dont-fear-the-monad/|Don't fear the Monad]]
* [[http://www.zohaib.me/yet-another-what-is-a-monad-post/|Yet another "What is a Monad" post]]
* [[http://mvanier.livejournal.com/3917.html|Yet Another Monad Tutorial (part 1: basics)]]
* [[http://www.idryman.org/blog/2014/01/23/yet-another-monad-tutorial/|Yet Another Monad Tutorial in 15 Minutes]]
* [[http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf|Monads for functional programming]]
* [[http://www.jianshu.com/p/31377066bf97|Scala和范畴论 -- 对Monad的一点认识]]
* [[http://zhuoqiang.me/what-is-monad.html|Monad 最简介绍]]
* [[https://blog.codecentric.de/en/2015/12/monads-demystified/|Monads demystified]]
* [[http://stackoverflow.com/questions/2704652/monad-in-plain-english-for-the-oop-programmer-with-no-fp-background/2704795#2704795|Monad in plain English? (For the OOP programmer with no FP background)]]
* [[http://james-iry.blogspot.se/2007/09/monads-are-elephants-part-1.html|Monads are Elephants Part 1]]
* [[http://www.jianshu.com/p/9ff3040c7159|Monads are Elephants(4) 翻譯]]
* [[https://darrenjw.wordpress.com/2016/04/15/first-steps-with-monads-in-scala/|First steps with monads in Scala]]
* [[https://www.youtube.com/watch?v=QqEeBoZ8qxA|Scala Monads Declutter Your Code With Monadic Design]]
====== 外部連結 ======
* [[http://www.haskell.org/haskellwiki/Haskell|The Haskell Programming Language]]
* [[http://patternsinfp.wordpress.com/|Patterns in Functional Programming]]
* [[http://blog.johantibell.com/2010/09/slides-from-my-high-performance-haskell.html|High-Performance Haskell]]
* [[http://www.well-typed.com/blog/70|The New Cloud Haskell]]
* [[http://blog.codacy.com/2015/07/03/how-to-learn-scala|How to learn Scala]]
* [[http://danielwestheide.com/scala/neophytes.html|The Neophyte's Guide to Scala]]
* [[http://pointlessfunctor.blogspot.tw/|Pointless Functors]]