Haskell 学习笔记一:基础

Hacks Apr 12, 2020

这是一个新的系列,主要讲讲我在学习 Haskell 的过程中遇到的一些坑和心得,希望能用最简单的语言给初学者提供一些帮助。整个系列预计会有三到四篇博文。主要会包含:

  • Basics
  • 数据类型
  • Functors, Applicatives, Monads
  • State
  • Parser
  • Interpreter

会写这个系列的原因是因为在初期我学得实在是太痛苦了,但是入门之后被深深折服,Haskell 实在是太优雅了。

Haskell 实在是是一门无比优雅且深奥的语言。才疏学浅[1],只能窥得冰山一角,权当抛砖引玉。

在写作过程中有参考多伦多大学 Albert Lai 教授的课程设计。

希望能给中文世界的各位一些帮助。
这玩意在工业界流行不起来是有理由的,再牛逼也得有人学并且学得会是不是

Eva-00

this should be in ayanami blue

Haskell 是一门函数式编程(functional programming, FP)语言。和我们最常接触的面向过程(procedural programming)和面向对象(object oriented programming, OOP)不同,函数式编程更像数学上的函数。一个显著的差别是 Haskell 几乎没有变量(其实是有的,但是我们先放在一边,因为确实和你想的不太一样)。对于习惯了 C 之类的我们来讲,学起来确实还是相当痛苦的。

我不打算覆盖很多的基础内容,互联网上有很多比我写得更好的资源。不过如果有需求的话可以加上一些。这个系列的主要目的是写写我在学习过程中遇到的难点。

国际惯例,先来一发 Hello World

main :: IO ()
main = putStrLn "Hello, World!"

函数

Haskell 的函数非常类似数学上的函数。

factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)

这是一个很简单的 factorial 函数。意思是给一个数,输出这个数的阶乘。

第一行:类型签名(type signature),输入一个整数,输出一个整数
二到三行:pattern matching(模式匹配?不知道正式翻译是啥)。这是非常有意思的地方。
第二行:如果输入是 0,则输出 1
第三行:如果不是,就递归输出它的结果(n*factorial(n-1))。

在 Haskell 里,执行函数会从前往后匹配,并且执行匹配到的区块。

调用它的方法也和其他的语言很不同,直接函数名+空格+输入,比如 factorial 0

同样的,如果有一个函数是这样的:

add2 :: Integer -> Integer -> Integer
add2 x y = x + y

add2 则接受两个 Integer 类型的输入,有一个 Integer 类型的输出。

但是魔法来了。如果只给 add2 提供了一个参数呢?

Integer -> Integer -> Integer 事实上和 Integer -> (Integer -> Integer) 是一样的,即 add2 函数收到第一个 integer 输入的时候返回的是另一个类型是 Integer -> Integer 的函数,第二个输入则被提供给这个函数。

举个例子,(add2 0),返回的就是一个类型为 Integer -> Integer 的函数。(add2 0) 1 则把 1 作为输入提供给了 (add2 0) 返回的函数,得到我们想要的结果。(add2 0) 1add2 0 1 是一样的。

今天先到这里。

下一集:Haskell 学习笔记二:数据类型


  1. 真的不是谦虚 ↩︎

aLPHAtOAD

太年轻,太简单,有时候幼稚。