技术分享 | Haskell 工程化的挑战和收获

Posted 编程语言Lab

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了技术分享 | Haskell 工程化的挑战和收获相关的知识,希望对你有一定的参考价值。

作者 | 韩冬
整理 | 编程语言Lab

5 月 29 日,由极客邦旗下 InfoQ 中国主办的全球软件开发大会 QCon 2021 北京站正式拉开帷幕。大会为期三天,来自 EMQ 的 CTO、首席开源官韩冬作为其中“软件研发方法”专题的出品人,于 30 日上午分享了“Haskell 工程化的挑战和收获”。

韩冬  拥有超过 6 年的 Haskell 编程经验,是《魔力Haskell》作者。曾担任清华《函数式编程》课程 19 年春季学期主讲人,是 Haskell 社区多个开源库的作者。目前在 EMQ 担任 HStream 产品 CTO 和首席开源官。

技术分享 | Haskell 工程化的挑战和收获

以下为韩冬分享的 “ Haskell 工程化的挑战和收获 ” 原文:

 Haskell 简介 

“Haskell is a standardized, general-purpose, compiled, purely functional programming language with non-strict semantics and strong static typing.”
—— by Wikipedia

Haskell 是一门历史悠久的编程语言,根植函数式编程体系:

   1958 年 JohnMcCarthy 发表了 LISP(List Processor),之后 LISP 家族⽣生不息,现存的实现包括 SBCL(Common Lisp), Racket(Scheme), Clojure…

   1970s 函数式编程语言 ML (MetaLanguage) 诞生,在接下来的几十年衍⽣出Standard ML,Caml,OCaml... 1969 ~ 1973@⻉尔实验室:C语⾔诞生

   1978 年 BrianKernighan 和 Dennis Ritchie 出版巨著《The C Programming Language》,史称 K&RC,⾄今 C 系编程语言已成主流。

   但是,⽜逼的计院教授们觉得这些语言还是弱爆了,于是在 1987 年聚在⼀起,要设计⼀个吊到爆的编程语言,这就是 Haskell。 

技术分享 | Haskell 工程化的挑战和收获

到现在为止,Haskell 是一门拥有超过 25 年历史的,拥有 GHC 作为主要实现的一个可靠的编程技术。

 为什么选择 Haskell 

根据 Github 2020 年的调查,虽然 Haskell 远远排不上使用最为广泛的语言,但却在最受程序员欢迎的编程语言榜上出现,并超过 Java、C++ 等常见的工业语言。
> 2020 最广泛使用的编程语言
技术分享 | Haskell 工程化的挑战和收获

> 2020 最受程序员喜爱的编程语言

技术分享 | Haskell 工程化的挑战和收获
这说明了程序员普遍对 Haskell 语言有使用的兴趣和热情。那么具体来说,我认为 Haskell 这门语有以下几个优势:
语法优雅
代数数据类型和函数组合使得代码变得紧凑而易于阅读,例如我们可以很轻松的高效实现一个 JSON 解析器:
  
    
    
  
data JValue = JNUll | JBool Bool | JArray [JValue] | JString Text | JObject (Map Text JValue) | JNumber Scientific
jvalue :: Parser JValue jvalue = jnull <|> (JBool <$> jboolean) <|> (JArray <$> jarray) <|> (JString <$> jstring) <|> (JObject <$> jobject) <|> (JNumber <$> jnumber)
jarray :: Parser [JValue] jarray = between (char '[') (char ‘]')     (jvalue `sepBy` (char ‘,'))
速度快!
和大部分人想象得不同, GHC 可以把 Haskell 代码翻译成高效的机器码实现,例如在著名的编程语言 Benchmark 排行中, Haskell 可以取得和 Java 类似的性能:
技术分享 | Haskell 工程化的挑战和收获
容易被测试
Haskell 的代码强调纯函数和 IO 分离,所以对 Haskell 代码进行属性测试是一件司空见惯的事情,例如我们可以很容易的描述 base64 编解码器的 roundtrip 属性:
describe “base64 roundtrip props " $ do prop "base64Decode . base64Encode === id" $ \ xs ->       (B.base64Decode (B.base64Encode xs) === xs)
高级运行时
GHC 除了提供高效的机器码生成之外,还提供了一个高级的 Haskell 语言的运行时,它拥有许多别的语言不容易实现的特性,例如软事物内存 STM(soft transactional memory):
  
    
    
  
transfer :: Gold -> Balance -> Balance -> STM ()
transfer qty fromBal toBal = do fromQty <- readTVar fromBal when (qty > fromQty) $ retry writeTVar fromBal (fromQty - qty)   readTVar toBal >>= writeTVar toBal . (qty +)
上面的代码原子性的操作了两个账户变量,同时使用了 Haskell 的类型系统杜绝了在运行事务时可能进行的任何 IO 操作。
对 DSL 的 First class 支持
由于 Haskell 语言提供了对自定义运算符、单子(Monad)和基于 typeclass 重载的支持,这使得编写领域特定语言(DSL)变得十分轻松和简单,例如下面是一段运行时生成 SQL 的代码:
  
    
    
  
select $ from $ \(b, p) -> do where_ (b ^. BlogPostAuthorId ==. p ^. PersonId) orderBy [asc (b ^. BlogPostTitle)] return (b, p)
==================>
SELECT BlogPost.*, Person.* FROM BlogPost, Person WHERE BlogPost.authorId = Person.id ORDER BY BlogPost.title ASC
通过上面的例子可以看出,Haskell 并不是一门“其他的”编程语言,它是一种对传统编程思路的颠覆和解构,通过提供和传统 C 系编程语言不同的抽象角度,这门语言可以让很多问题变得更容易、更好的被解决。

 Haskell 生态现状 

主要实现
GHC 作为 Haskell 目前的主要实现,每年会有若干小版本发布,平均1到3年会有一个大版本,同时代码提交的频率和数量都非常高。由于 Haskell 本身在学术圈的地位,也导致了需要编程语言专家会帮助 GHC 继续演进。
业界应用

这里简单地列举了一些互联网巨头使用 Haskell 编写的知名项目:

  • Facebook - sigma

  • Standard chart - Mu

  • Microsoft - bond

  • GitHub - semantic

> 社区建设
Haskell 社区的中央仓库 hackage 目前每天都有数十万的下载量和几十个新发布的库函数,对于一个小众语言来说还算可以。

 Good, Bad and Controversial 

  • 好的地方
   先进的构建、文档生成工具:cabal, haddock
   良好的编辑器支持,提供基于 repl 的开发体验
   语言本身提供的类型保证、丰富的抽象能力
   FFI 调用 C 函数非常方便
   高级的并发支持:lightweight thread, STM, etc.
   很多库函数可以使用
   易于重构

  • 不好的地方
   很多库函数维护情况不理想,文档较为粗糙
   社区活跃度不够,国内使用人数较少,招聘困难
   官方的核心库有许多初学者需要避免的坑:String, Lazy IO, etc.
   编程思路和传统语言偏离较大,不易上手

  • 富有争议的地方
   学习曲线陡峭,导致一方面新人上手到写生产代码需要很长时间,另一方面招聘到好的 Haskell 程序员,一般来说也都是各方面非常优秀的。
   Haskell 语言不强调对底层机器的控制能力
   Haskell 的代码非常强调数学概念

 我们的一些工作、未来展望 

生态补齐计划:Z.Haskell

鉴于 Haskell 社区薄弱的工程生态,我们发起了 Haskell 工程生态项目 Z.Haskell(http://z.haskell.world/),该项目旨在解决常见的工程需求,例如 UTF-8 文本处理,二进制、文本序列化、反序列化框架,常见的文本、二进制格式支持:JSON,MessagePack等等。其中值得一提的是目前 Z.Haskell 提供了基于 libuv 的高效 IO 方案:

技术分享 | Haskell 工程化的挑战和收获
通过把 libuv 的异步事件循环和 GHC 的运行时提供的轻量级线程结合起来,我们实现了同步编程范式下的 IO 自动异步化:
技术分享 | Haskell 工程化的挑战和收获

而由于 GHC 运行时对多 CPU 支持已经非常完善,所以这套方案能够很好的在多核架构上运行并发挥并行处理的优势:
技术分享 | Haskell 工程化的挑战和收获
除了提供高效的 IO 解决方案之外,我们还提供了一套基于 Botan 的密码学工具箱:
   Random numbergenerators.
   Block Cipher andsymmetric cipher.
   Hash.
   MAC.
   Key derivationfunctions.
   Password hash.
   Multiple precision integers.
   Public keycreation, import and export.
   Public keyencryption/decryption
   Diffie-Hellman keyexchange.
   Signaturegeneration & signature verification.
   X.509 certificates & X.509 certificate revocation lists.
   One time password.
   AES Key Wrapping.
   Format PreservingEncryption.

这些将成为未来我们构建 TLS 协议的基础,未来 Z.Haskell 项目的路线路包括:
   •     TLS,HTTP/ HTTP2 框架
   常见的数据库、缓存、消息中间件连接
   分布式场景支持,raft 实现

这些都将会进一步降低初学者入门 Haskell 和进行工程实践的门槛。

 后记 

随着全球软件研发中心从欧美向中国转移,国产软件正在经历从业务 -> 框架 -> 编程语言 -> 操作系统的一系列下钻的过程,我希望在未来,有更多的中国公司进入到底层的开发领域,并贡献更多的业务价值,并从标准的高度构建技术壁垒。