精通haskell pdf是一种怎样的体验

精通 Haskell 是一种怎样的体验?
按投票排序
咳,之前 @祖与占 提到要描绘下Haskell社区的大婶(神),但。。。下面没有了。。。。我来上一个Edward Kmett大婶(因为偷偷尾行过一段时间)的事迹 (github:ekmett),用语会比较夸张,但求一个笑果。有一天,Ekmett爷想在Haskell里耍一下OpenGL,发现在Hackage上OpenGL绑定的库有一堆:Ekmett爷顺手挑了一个,上下耍了几圈,觉得不够尽兴:丫写的烂库,不能满足爷的任(需)性(求)!!于是出现了下面这一幕(友情提醒,注意日期):Ekmett爷顺手挑了一个,上下耍了几圈,觉得不够尽兴:丫写的烂库,不能满足爷的任(需)性(求)!!于是出现了下面这一幕(友情提醒,注意日期):可惜应者寥寥。。。。。。可惜应者寥寥。。。。。。Ekmett爷:不行了,不行了,不能忍了!!!袖子管撸起来,轮子造起来,打酱油的围起来~~袖子管撸起来,轮子造起来,打酱油的围起来~~几天以后,Hackage上,一个叫做
的库,被上传了。。作者:Sat Nov 1 22:44:40 UTC 2014 by EdwardKmett。。。(注意日期注意日期注意日期。。。。)这个库包含的模组是这样的!!!(注意哈,要拉好几页哈,我就不拉了......)这个库的代码结构是这样的:(注意src文件夹哈)这个库的代码结构是这样的:(注意src文件夹哈)其他Binding库作者: WTF!!!!!!!!!!Ekmett爷:俺从来不屑写binding代码,每当写binding时,我写个生成binding的Generator。。。。嗯,以上。。。。。。。。。。Ekmett爷的总结如下:懂Haskell、会数学、任性!!!
回答这问题要冒说自己精通Haskell的风险。首先我并不敢说我精通Haskell,目前学的东西都只是一知半解,杂而不精,这里我只回答,不承担风险。也未见有人说自己精通Haskell,都是互相冠以精通的称号,从来不是自封。SPJ做为Haskell的创造者也没敢说自己精通Haskell,而更多的是有不明白的虚心向社区里的人们请教,比如Dependent
type, type safe coerce等等,还说如果有人有更好的办法请跟我讨论。我曾经见过SPJ本人,看见过他跟hlint的作者Neil
Mitchell讨论问题虚心的态度。我想本贴的题目改成深入了解Haskell再用它来编程是什么样的体验。我的朋友邀请我来回答,我觉得这个题目太大,之前在微博上请了一些强人,但是都推托没有回答,那我就把我看到的简单说一下。(注:部分代码来自Don
Syme对于F#写C#比较的教学视频)1、代数数据类型与类型类(ADT与typeclass):使用ADT体验上觉得要比OO轻松,尤其是在写语法树的时候,如:data Exp = True
| And Exp Exp
| Or Exp Exp
对比C#可能要写成下面这样,Java可能要更麻烦。public abstract class Exp {}
public abstract class UnaryOp : Exp{
public Exp First {get; private set;}
public UnaryOp(Exp first){
this.First = first
public abstract class BinExp : Exp{
public Exp First{...}
public Exp Second{...}
public BinExp
另外对于Show类型类,即可以打印输出的类型的集,还有Eq等等是可以通过deriving自动实现的,Java需要重写toString还有equalTo之类的方法,而且是对于每一个之后定义的类。对于这类明显可以自动做的事情C#、Java无法做好(如果大家有方法在Java里自动生成toString函数来打印所有成员变量的方法希望告知)如果你知道Haskell的类型系统就知道,Haskell中Exp是类型、而And、Not是值的构造器,而Java、C#将这两者概念统一,无法进一步抽象,所以是不会有Kind(类型的类型)相关的概念。之后再淡Haskell类型类:类型类与接口相似,与abstract
class更近似,但是比接口强大与抽象类又不一样。首先Haskell的类型类允许定义最小实现与互相实现,如:class Eq a where
(==) :: a -& a -& Bool
(/=) :: a -& a -& Bool
x /= y = not (x == y)
x == y = not (x /= y)
{-# MINIMAL (==) | (/=) #-}
只需要定义等与不等的一个你就免费得到了另一个。如果你要写一个函数需要这个类型同时实现Show与Eq两个接口,那么你需要合并两个接口:interface Show&T&{ String show (T a);}
interface Eq&T&{ boolean eq(T a, T b);}
interface ShowEq&T& extends Eq&T&, Show&T&{}
然后再转而将你需要的类型实现ShowEq才能应用基于这个接口的类型,这样就显得罗嗦。所以说Java的泛型更像是打了一个补丁,并没有很好地原生支持,相信C#也是一样。Haskell里要定义一个基于多个类型类的函数完全不需要这样,只需要把类型类限定加到函数的上下文中即可:foo :: (Show a , Eq a) =& a -& a -& (Bool,String)
所以我以为面向特质这样的设计要比接口更好。下一个说的就是泛型已然已经忘记Java是在1.5还是1.4出的泛型,受到多人的吹棒,其实C++的Template跟Java泛型都没有解决本质的问题。记得看过C++的Template是宏实现的,对于不同的类型变量会重新生成新的代码编译,并不是严格意义上的代码复用。Java的泛型是在语法基础上改动,加了静态的类型检查,可是写起来还是相当繁复。并不了解C#泛型机制。这里比如写一个C#的swap,将一个tuple的两个元素调换:Tuple&U,T& Swap (Tuple&T,U& t){
return new Tuple&U,T&(t.Item1,t.Item2);
Prelude中定义的Tuple用起来则方便很多swap (a,b) = (b,a)
类型的声明可以省去,因为Haskell可以推断,而即便加swap
:: (a,b) -& (b,a)也要比C#或者Java中反复地加类型标记干净省事得多,没有类型推断,我们要不断地重复写类型T、U作为标记为Java能够检查它。而定义一个Tuple这样的类型使用ADT也相当容易,下面的是单向链表data Pair a b = Pair a b deriving (Show, Eq, Ord)
data List a = Nil | Cons a (List a) deriving (Show, Eq, Ord)
单就上面的两行可能Java、C#就需要做很多无谓的工作来实现。Java、C#中的泛型在Haskell只是参数化类型,多态函数id、const、flip到处都是,例子多得举不过来,我也从来没有见过Haskell把泛型拿出来当特性来宣传过,因为根本不值得一提。泛型(Generics)一词在Haskell用来代指一个更强大的特性,通过使用ADT构造的基本方法——Unit、积(Product)、和(Sum)来构造对于任意类型的同构关系,使用序列化、Eq、函子类型类的自动生成成为可能。有兴趣的可能读一下A
Generic Deriving Mechanism for Haskell一文,说到这里有点跑题了。2、高阶函数Java与C#中是没有高阶函数的,即返回函数,以函数为输入的特性。它们只能把函数包在class里面然后进行传递,不具有一般的特性。常常我们需要做一些重复的事情,比如把一个类型,列表或者其他的容器里的值应用一个函数,传统的语言里就是写一个for,然后对于新建一个容器,对每一个都应用一下函数,再返回新的容器。这样的模式总是出现,而Haskell或者其他函数式语言里直接用map就可以了,对于树,还有其他容器Haskell的Functor类型类就是做这个的。再加之有fold函数,这些东西总是在反复在实践编程中出现,支持高阶函数的语言直接就全用高阶函数做好了。有人在Haskell吐槽过($)还有(.)运算符,我的学生不理解,我研究生的同学,网上也见有人说这运算符很奇怪,这只是参数从右向左依次进入函数体中的一个运算符:Prelude& not $ even $ (+1) $ 5
5+1 = 6 --& even 6 = True --& not True = False
只要你喜欢,你可以定义一个(|&)
= flip ($)把上边的写成 5 |& (+1) |& even |& not
这就跟F#一样了,F#可能更喜欢这种口味吧,顺序式就是从上至下、从左至右,改变一下就不爽了。而这种东西在Haskell中恰恰是最自由的,十分随意。也正是由于高阶函数与类型系统,try与catch这样的东西在Haskell里完全可以用函数来实现,所以你会见到各种库自己会有自己的处理异常的函数,这就是灵活引起的坏处之一,不得不说Haskell的异常管理就是个灾难。任何单一的异常库可能都满足不了所有的需要,所以大家都写自己的。3使用哲学初入门的时候觉得Haskell的类型系统真的不难,并且有很多很傻的东西,为什么会有id
:: a -& a、const :: a -& b -& a这么傻的函数,鬼才知道有什么用(刚学的时候真的是这么认为的),Applicative中的(&*&)
:: f (a -& b) -& f a -& f b就是把一个容器里的函数应用到一个容器里的值中,为什么一切在Haskell里看上去都是那么傻,看上去都是这么无用?在之后的研究与学习中发现自己知道的越少,自己暴露的愚蠢就越多,这些东西在Haskell里都是有大用的,尤其是Applicative具有很强的一般性。Haskell就是这样,由于每一个函数做的事情非常有限,粒度非常小,所以你单独看他们会觉得都是没什么用的,你单独看id
:: a -& a函数的时候,无论你给什么值,它都会返回你给的那个值,你输入5就返回5,你输入True就返回True,你当然看不出有什么用处。举两个例子,一是Parser组合子里的选择&|&,直接返回return,顺序&&=,分析一次以上的some、分析0次以上的many、char、digit这些最容易的小函数组合起来最终会得到可以分析上下文无关文法的大的Parser组合子。另一个例子是控制并发的STM,主要只实现了返回return、顺序&&=、选择&|&、重试retry
4种函数就完全可以实现了你在并发里需要的一切。当你不屑于理解这些小东西的时候你就永远也无法理解它们的组合。你在单独审视一个函数的时候是没有用的,只有当你小心地把它们组合起来你才会知道它们可以用来做什么,这就是很多人觉得Haskell很多概念东西无厘头的原因。哲学中最重要的不过Monad了,总是有人骂Monad,现在说说Monad,这东西刚一学真是不理解为什么要用,当初唯一的感觉——这是虎人的!因为Monad并不能给你带来更新的特性,它只是带来了一种更有效地组织代码的方式。之前的STM与Parser都是Monad,Monad是一种设计模式来帮助你分离有不同作用代码。当代码中需要管理资源的分配与回收,你需要Resource
Monad,当要记录状态你需要State Monad、当你需要用元编程来生成Haskell代码你需要Quotation
Monad,当你同时需要他们的时候,你用Monad转换器把他们组合起来,他们之前不会互相影响并且每个Monad的行为都被严格地限定了,你不可能干很出格的事情。Haskell中的Lazy
IO十分难以控制,也并不符合Haskell的使用逻辑,于是就有了Iteratee这样的库。通过stream来源、中间变换处理、还有处理这些stream去向的Sink间的组合达到高度的模块化,自动控制资源回收、内存使用的目的。(前段时间看好像Scala目前正缺这玩意)4类型系统除了简单的HM类型系统以外,还有任意Ranked的类型,可以更为严格地控制函数与其行为,最为著名的例子就是ST
Monad与SYB中的Data类型类中的一些函数,这也使得Haskell处理动态类型成为可能。Haskell可以像Scala一样做动态类型匹配,但是有些麻烦。类型之上还有类型的类型,即为Kind,需要一个类型参数的类型构造器记为*
-& *,像Java中的Vector就这样,而两个的则为
* -& * -& *,之前的Tuple就是这样。假定我们要想办法来表示类型,以便在运行时查询一个值的类型,就需要定义下面这样的重复。(Java中不需要主要是这样,因为有instanceof关键字,主要是因为Java中没有类型构造器一说,Exp类型中And也做为了类型继承了Exp,窃以为这在工程逻辑有些混乱,And构造出来的是一个值,而并不应该具有类型属性,可以Java中需要定义他为一个class,对于抽象的方式我更喜欢ADT)class Typeable a where
typeOf :: a -& TypeRep
class Typeable1 t where
typeOf1 :: t a -& TypeRep
class Typeable2 t where
typeOf2 :: t a b -& TypeRep
以上的t分别需要0、1、2个参数,Kind分别为*、*
-& *、* -& * -& *,所以需要分别定义,而有了Kind多态,则可以一次完成。不同的是需要一个代理类型来代表a的具体类型。无论是写成t,t
a这种都是不对的,因为我们并不需要有一个具体的值,所以用Proxy来指代。class Typeable (a :: k) where
typeRep :: Proxy a -& TypeRep
这样在动态查看Tuple&U,V&这样的类型在Haskell里面做起来就十分方便。有了kind多态、再加上Proxy还有把值“提升”到类型上,就可以干一些比较有趣的事情了。data Nat ...
data Vec :: * -& Nat -& * where
Nil :: Vec a 0
Cons :: a -& Vec a n -& Vec a (n+1)
通过这样定义类型可以指明一个列表的长度,如此一来就可以限定我们的函数只在某些特定长度的列表上工作减少可能出现的错误,更为重要的是这种错误是在编译期就能找到的,可以进一步地应用到矩阵的运算上,通过定义Matrix
(m::Nat) (n::Nat) Int限定一个m乘n大小的矩阵。这种类型对于某些问题还是不能进一步限定, 因为在运行时函数不能从类型中取得值,但是随着GHC的进化,已经可以很好地做到这一点了。比如下面来自GHC手册的例子,其中Proxy
2是类型,2是类型,而非值。 这里就是Dependent
type了虽然还做得不好,比起Agda要差。& :m +GHC.TypeLits
& :set -XDataKinds
& natVal (Proxy :: Proxy 2)
说到这里,可能更多的人是在问这些有什么用。我觉得这里问题不是什么,而是你是否会用,怎么用。我的理解就是这种类型可以在一个类型的基础上限定出一个类型从而更好地让类型系统帮助你组织出正确的程序,下面是唐凤的代码:data Matching :: Symbol -& * where
Matching :: KnownSymbol regex =& Matching regex
Match :: String -& Matching regex
instance Show (Matching regex) where
show m@Matching = symbolVal m
show (Match string) = string
5 Int类型中我们可以说一个长度为5,里面全是Int列表,而这里我们则可以说Matching
“a?b?c?”是一些满足“a?b?c?”的正则表达式的字符串,而不是所有全体字符串String类型。xs :: [Matching “a?b?c?”]
xs = list 100 serises
[,a,b,ab,c,ac,bc,abc]
类型起文档作用,程序员直接就可以理解这样的函数,使用起来也相当方便,借助惰性求值,这样的符合这样正则表达式的字串要多少给你多少,(当然这里只有这么多,没有100个)方便了自动测试工作。5 元编程与引用Ruby一直说自己有元编程能力,其中Haskell里也有,但是Haskell从来没特意宣传。元编程可以极大地消去重复的代码,比如:zip :: [a] -& [b] -& [(a, b)]
zip3 :: [a] -& [b] -& [c] -& [(a, b, c)]
zip4 :: ...
这些函数可以先定义一个“元函数”zipN
:: Int -& Decl,zipN 4就会帮你生成zip4。使用元编程可以帮助我们自动化很多事情。比如aeson库自动生成FromJSON与ToJSON的类型类实例,完全不需要怎么动手,并且生成FromJSON跟ToJSON类型类实例可以并在一句一起生成。Java需要借助IDE工具来生成访问器与设置器函数实在不是好的解决方法,借用Haskell的Lens库一行就可以生成需要的函数。配合引用(QuasiQuote)可以没有限制地向Haskell里加入语法糖。可以直接引用XML、JSON,Haskell会自动帮你生成对应用的data。引用一门语言的源代码(多数为DSL)QuasiQuote可以帮你自动生成AST,可以真正做到一劳永逸,不写重复的、机械的代码。6 GHC的效率与惰性求值首先说一门语言慢是不对的,讨论的应该是对应有编程器实现。广受争议的GHC的效率是一个很令人头疼无语的问题。见过很多人用C写一段程序然后用Haskell写一段程序,编译一下然后得出GHC慢的结论,再对惰性求值这种拖慢速度的特性踩上几脚。更无奈的是你没有办法进行反驳,因为这不是几句话能说清楚。每次我都想回为什么你不比谁的代码更美观。我见过很多插中GHC软肋的代码,不知道他们是有心无心。常见的例子有用递归算阶乘。因为运行的时候结果主要是通过一个地址指向一个内存中Thunk,对Thunk
force求值再读到CPU进行运算。再加之其他运行系统以及寄存器使用等原因,GHC函数返回使用的是跳转,而非ret(在Reddit上看Simon
Marlow有讨论,那个Fibonacci函数总是要比C慢3倍),结果GHC要比GCC慢十几倍。Haskell是否可以写出更快的代码呢?当然是可以的,注意一点,Haskell惰性求值只是特性,不代表Haskell只能惰性求值,Haskell里的严格求值,!模式,UNPACK、RULES、INLINE编译器标记,Unboxed的类型都是可以用来提高效率的。但是层数太多的递归还是会比GCC慢,但是实际中递归的深度有多少能超过2000的?惰性求值是不是一个好特性?这个问题应该改成你会不会正确地使用,或者改成Haskell可以严格求值,那么默认Lazy是否是一个好的选择?Haskell的表达式形式分为3级,WHNF(弱首范式)、HNF(首范式)、NF(范式),其中NF是一个不可以再继续化简的表达式,对于其他语言如F#跟Scala我不是特别了解, 但是表达式化简的过程由繁入简是符合直觉的,从WHNF到HNF到NF对应默认的惰性求值seq($!)与deepseq($!!)。那么GHC的效率是否高?这个问题我想不如改成谁来用GHC效率会高?我看到的普遍现象是大多数人的第一语言并不是Haskell,没有在Haskell这种学习曲线本来就陡峭的语言上投入更多时间与精力,所以自然不会写出比Java、C更快的代码,写出了几行Na?ve的Haskell代码就跟C比然后得到了GHC比GCC慢的结论,明显是不公平的。我觉得一个人可能要花比C、Java多几倍的精力来学Haskell才能写出高效的Haskell代码。我没有过实际的Haskell开发经验,所以并没经验可供分享,不过就我看到的真正的实践中的API如Aeson,分析JSON的效率在2.2GHz的i7上可以达到40M/s,编码可以达到100M/s。而对于其他语言JSON相关的库我并不清楚。。并不清楚cjson会不会更快。Simon Marlow在Facebook用Haskell实现的Haxl也要比原有的C++框架快,并且核心数增加,这个差距几乎不变。另外唐凤也在IBM做了一个字符集转换的程序,用Perl每天在340MHz的IBM主机上只能处理到2.5GB,远没有达到一天处理25GB的要求。而且他已经试过用C/C++汇编去改写某些特定的部分都没有达到要求。也因为Haskell有惰性求值特性,内存使用大幅减少,效率也只比直接复制慢了2%(在视频的第34分钟)。
(推荐大家看看这个视频) 并不是说GHC一定会比C快,但至少可以说明GHC是可以编译出高效的代码的。当然语言也是有适用性的,如果你真的需要一些结构体、内存变量、想手动管理内存分配回收,那么可以用C再通过FFI给到Haskell,把更抽象的逻辑交给Haskell,语言都是有适用范围的而且没有万能药。如果一个人对于表达式形式WHNF、HNF、NF以及求值顺序,运行时生成报告这些概念都不懂就说Haskell慢多半是人云亦云的。你需要更多精力学习才能写出快的Haskell代码。7 使用的感觉有一点已经没有必要争论,函数式语言包括Scala、F#、Haskell完成一件事情的代码量要少很多,少1~10倍是多数情况,极端情况少20倍左右也不是不可能,这一点在《黑客与画家》上有提,用Haskell解决8皇后问题5~6行,而Java我足足用了50行而且我不觉得有人会写得更精简。不相信的话可以试着把下面一门toy语言的AST定义译成Java或者C#,看看要多少行代码:data Exp = Val Int | Var Name | App Op Exp Exp deriving (Show, Eq)
data Op = Add | Sub | Mul | Div
deriving (Show, Eq)
data Prog = Assign Name Exp
| If Exp Prog Prog
| While Exp Prog
| Seqn [Prog] deriving (Show, Eq)
在研究语言时常常要干这些事,比如实现Hoare逻辑计算、在这个toy语言上做Model
Checking,显然函数式语言是首选。研究生的时候写一个Lambda演算计算器只有了几个小时,书里的练习可以自动帮我做好。考试的时候写了一个LTL转Buchi自动机的程序也没有很费时间,更重要的是Haskell中的定义可以跟数学过程一一漂亮地对应,绝对不可能出错。在学习计算机语言原理时,课上是用Haskell,但是我为了了解一个概念看了一本书用Java实现一门语言的过程,对于没有经验的我就是灾难。需要写的代码少了,使用函数式语言对于程序员个体的战斗力的提高就相当显著了,而我觉得非FP的语言想以这种倍速提高战斗力有些困难。我也会看到其他语言在宣传各种特性,如Java8加入的Lambda表达式,我贱贱一笑,心想:这功能竟然会引起大的骚动。Ruby的元编程Haskell也是有的。Python的协程Haskell有库实现,不需要语法支持(通过Monad与CPS实现)。Nodejs的异步同样也有库实现,同样不需要语法支持。至于goroutine我并不是特别明白为什么呼声如此高,可能我没工程经验吧,但是给我的感觉就是一个非守护的轻量级线程,这Haskell的轻量级线程还有与异步的库很像。由此我想说的是Haskell是相当灵活的,其他语言的特性不是有原生的实现就是有库的实现。Haskell是一门很精深的语言,有人说Scala比Haskell更难,我觉得专精C++、Haskell与Scala都是很困难的,难的地方还不太一样,曾经以为学完了C++的指针、Template就完了,结果看到Boost库的实现才知道之前学到的只是皮毛。我花了几年的时间研究Haskell再去参加一些会还有看视频才能大概理解他们说的是什么东西。去年这个时间看Oleg实现的Iteratee的代码还是不明白,现在看了很多视频还有文章、用了Pipe、Conduit这些库才能略窥一二。有一位Yale毕业的博士朋友,现任职于Intel,他写的50行的异步转协程的代码我不太能理解他在干什么,虽然CPS我也明白一些,但是无法理解。另外一位苏格兰的博士实现了GHC中的OverloadedRecordField扩展,我看了一下实现,能理解,使用了好多特性,但是觉得这个实现好优雅,吾不能及也。这就是我的感觉,学到现在一样还是有很多看不懂的。相信可以让大家从侧面看出学习的陡峭的程度,并且GHC正在以非常快的速度进化。这里我相信唐凤一定算得上专精Haskell了,对于函数式编程的感觉,在他上面的视频里的第9分钟是这样讲的:“大事化小,小事化无,以无事取天下”。把很小的东西,一个一个组合起来就可以得到一个非常非常复杂的程序。视频最后他说到IO的定义,IO以真实世界的状态为参数,返回真实世界新的状态跟一个类型为a的值,你会产生幻觉,以为真实世界不过是函数里的一个参数。Haskell的目的就是要观察这个世界,要改变这个世界,创造新的价值。这里再给一次视频地址对Haskell的普遍误解:Haskell因为惰性求值很慢。之前已经在第6部分讨论了,取决于你多了解Haskell。Haskell没有办法输出中间结果。unsafePerformIO函数专门来干这事,只是Haskell不推荐你这样做。可以用Debug.Trace库Haskell是纯的,没有变量,所以没法debug。逻辑不对,Debug.Trace就是干这个的,GHCi也可以设置断点,只是Debug的方式可能跟你想得不一样,不可以拿顺序式来要求函数式。Haskell一样有IORef作为变量。Haskell没有OO里的一些东西,所以不适合做工程。太扯,不是只有OO语言才能应用OO的思想,视频中唐凤也有说他也有把OO译到Haskell,OO的封装、多态、泛型FP语言里一样有。Haskell的大项目之一就是GHC本身,已经过了25年还是可以维护,不知道可不可以说明Haskell适合工程。只是没有那么多Pattern,Pattern是反复出现的东西,大分部这在Haskell里早就被做好了,只等你用。Haskell没有成熟的东西。Haskell有Yesod、Fay、Perl、XMonad。你会用咩?回应在Haskell
Core Dump贴中的Haskell没有Core Dump。这个是从Haskell
wiki上来的
有人说strong typing means no core dumps逻辑不通。我的理解是:这里主要是说类型检查可以检查出来导致崩溃的错误(当然有吹牛的成分),Haskell不需要管理内存,又是纯函数式,所以不需要core
dump,作为懂行的人你看看就行啦,什么快速排序、代码易懂、没有Core dump这些都是骗人进来学Haskell的。后面的代码根本不易懂,Monad,Monad
Transformation,Arrow虐爆人的头,出了错误当然要适当分析,分析System
FC,core dump、汇编,Haskell之前还有type
family以及coerce引起的段错误,这都是有可能的。为骗人进来学的一页wiki搞得这么认真,作为懂行的人都看不出来,你输了。回应Haskell的类型系统设计不严密,没有达到设计者吹嘘的样子。(在Haskell
Core Dump贴中看到的)。Coq、Agda的类型系统很严密,Agda本身没有被验证,但是是Haskell写的,Coq据说用手工验证过,必然比Haskell严密,你会去用他们吗?Haskell是在鼓吹Strong
typing,怎样?其他语言加个泛型、lambda就各种宣传,人们为什么不能接受Haskell吹吹强类型?如果Haskell说依赖类型有多少人懂,能吸引多少人进来?Haskell真正要干的事情是主页上说的rapid
development of robust, concise, correct software,快速地开发健壮、精确、正确的软件。效率没有在上面,虽然它可以很快。很多功能都没有体现,只是把简单的露在上面,下边巨大的冰山你不走近是看不到的。最后我觉得为了某种特性去了解一门语言是好的,Go、Ruby都好。你要是为了学习一门语言中思考的的逻辑与思想,那就是极好的,上之上也。为了了解函数式的各种概念,Haskell值得你一看。
感觉@阅千人而惜知己 的答案少了点体验 :D ,虽然我本身不精通Haskell, 但是偶尔也会观摩下Haskell社区的大神, 这里就不说Haskell社区里比较有名的两个Simon(Simon Peyton Jones和Simon Marlow) 想从三个角度(大神)来说一下"精通"Haskell是怎么个样子的....Edward Kemtt Dan Piponi
Lennart Augustsson
精力不够只说LA好了,谢
说了EK.LA:
应该是Standard Chartered 里Haskell技术部门的大佬, 根据Haskell wiki的介绍Standard Chartered has a large group using Haskell for all aspects of its wholesale banking business根据14年八月这个招聘信息We have more than 2 million lines of Haskell, and our own compiler.据说可能是世界上最大的商业Haskell codebase, 还记得天津渣打招40个Haskell程序员...btw, 渣打用的是一个Haskell的方言叫mu, 不过是strict, 而且还可以跟Excel交互, LA也是Haskell其中一个实现HBC的作者, 更多关于渣打对Haskell的使用可以看最底下的ref.hmm...augustss是怎么个精通Haskell法捏...其中一个杰作就是在Haskell里写Basic:
(不帖代码据说会少点赞{-# LANGUAGE ExtendedDefaultRules, OverloadedStrings #-}
import BASIC
main = runBASIC $ do
10 GOSUB 1000
20 PRINT "* Welcome to HiLo *"
30 GOSUB 1000
100 LET I := INT(100 * RND(0))
200 PRINT "Guess my number:"
210 INPUT X
220 LET S := SGN(I-X)
230 IF S && 0 THEN 300
240 FOR X := 1 TO 5
PRINT X*X;" You won!"
260 NEXT X
300 IF S && 1 THEN 400
310 PRINT "Your guess ";X;" is too low."
320 GOTO 200
400 PRINT "Your guess ";X;" is too high."
410 GOTO 200
1000 PRINT "*******************"
1010 RETURN
这个东西展现了Haskell强大的DSL能力...回到augustss的老本行,实现. 很多对Haskell的介绍是Haskell是一个用于学术研究的语言bla, bla...究竟是怎么个学术法? 相信不少人接触Haskell的第一件事就是去下载安装一个GHC, 现在好多做研究的就是写一篇论文, 在Haskell之上加个功能, 然后就成了一个GHC的extension, 又或者成为Haskell一个库, 所以就有"Sometimes documentation is an academic paper"这种说法, 看Haskell 98, Haskell 2010的spec才多少页...GHC的文档又有多少页, 别以为Monad一个东西有多难懂, 后面paper千千万...呵呵而augustss的牛B之处在于, 他能对这些东西的历史如数家珍! 前端时间社区有好心人搞了个 , augustss一个个给这些extension讲了下它们的历史, 背后的那篇peper...
下一个版本没有augustss做co-author我不服气啊!这么个样子应该算是精通Haskell了吧? 我就不说augustss的HBC, 几年前跑分能跑赢GHC的 (GHC背后有巨大的财团M$支持! ) . 不是精通Type Theory, Category Theory的才叫精通Haskell =. =! 那些只是基本姿势而已啦 =v=夹带个私货.Haskell呢, 不是有个很唬人的货叫monad嘛, spj告诉我们说它好多东西都能用它来抽象(), 某天看到个python decorator的例子def before_after(f):
def decorator():
print('before')
print('after')
return decorator
@before_after
def hello_world():
print('Hello, world!')
熟悉OO的人说, 这货看着像AOP啊...熟悉Haskell的人说, 这货看着像Writer Monad啊...放狗一搜:
(还以为我能发paper了TAT就是这个感觉! Ref: augustss在CUFP11的介绍
今年Don Stewart(RWH作者)发布的招聘信息, 下面渣打使用Haskell的介绍 Don Stewart在Google Talk对渣打使用Haskell的介绍, 谢谢
的回答,能感受到其功底深厚,只是要求受众得有一定Haskell基础才能看懂。我作为一名接触Haskell短短两三年的本科码农,更不敢说自己精通Haskell,也斗胆来分享一下关于Haskell的一些体验。----------------------------------------------------------------------------------------------------------------先简要回答楼主的问题,:Haskell(以及其它函数式语言)和C/C++等命令式的语言的区别主要还是在于思想:命令式语言需要教计算机“怎么做”;而函数式语言是要告诉计算机“是什么”.具体到代码中,就是等号的作用,命令式语言中的等号,是一个赋值操作;函数式语言中得等号,是在下一个定义。举个栗子:命令式:西红柿炒鸡蛋 = 炒(西红柿,鸡蛋)
这个时候无论你要不要,计算机已经把西红柿炒鸡蛋已经做好了。即使你不想吃了也不能退单了,菜都已经给你端上来了,不想吃自己扔掉好了,反正钱(CPU,内存)是要花掉的。至于那个等号,只是为了方便在你想吃的时候可以拿这个内存地址取到这盘菜而已。函数式:西红柿炒鸡蛋 = 炒 西红柿 鸡蛋
这个时候你只是下了个定义,相当于把菜谱念给计算机听,告诉它西红柿炒鸡蛋这道菜,是西红柿和鸡蛋炒在一起的结果,计算机只是记住了菜谱而并没有去炒菜。命令式语言是工程师的语言,函数式语言是科学家的语言。很小的时候老师问我长大后的梦想,尽管俗,但是我真的想成为一名科学家。后来因为生(cheng)活(ji)所(tai)迫(cha),变成了一枚工程师。在我几乎忘记了当初雄心壮志的时候,Haskell,让我觉得离梦想近了一些。。。虽然我这辈子可能都没办法“精通”Haskell了,但当我打开Notepad++写Haskell的时候,就是这样一种体验。。。----------------------------------------------------------------------------------------------------------------前面是体验,后面就是瞎扯了,主要是看了同学的回答,觉得有些东西不吐不快。三年前从一家非985,211的大学计算机系小本毕业,来到了某家银行供职。刚入职没多久,老大丢过来三本书,一本《Think in Java》(无奈,就是这么恶俗),一本《Future, Option and other Derivatives》(算是投行必读了),还有一本,就是《Real World Haskell》。。。另外两本都能读懂,不过这本《RWH》完全看不懂,只好找网上翻译的中文版,只有前几章被翻译了,后面的Monad是个球啊,完全理解不能。。。在我困惑的时候,发生了以下对话:我:这个Monad看不懂啊。同事:别问我,我也不懂,问XXXXXXX(另一个同事的员工编号)去。我(在outlook里键入XXXXXXX):Donald Stewart? 这是谁啊?同事:作者。我:啥?同事:《RWH》的作者。我:卧槽!《RWH》: 后来稍微会了一点,开始改Haskell程序,不会的地方,就去查Hoogle,碰到不会了的地方,向同事请教。我:我想实现BALABALA,有没有什么现成的API可以用啊。同事:别问我,我不知道,问XXXXXXX(另一个同事的员工编号)去。我(在outlook里键入XXXXXXX):Niel Mitchell? 这又是谁啊?同事:写Hoogle的。我:卧槽!Hoogle: 再后来,写了一个递归的函数,我觉得自己没问题,编译总是报错,又请教同事。我:这个为毛编不过啊,帮我看看,我觉得没啥问题啊。同事:奇怪,语法应该没问题,估计是编译器的事。我:那怎么办?同事:问XXXXXXX(另一个同事的员工编号)去。我(在outlook里键入XXXXXXX):Lennart Augustsson? 别告诉我咱用这编译器是他写的啊。同事:就是他。我:卧槽!Lennart: 学Haskell的时候,真的是怀着无比敬畏的心情在一步一步学的。一开始还不敢打扰大神,只敢在群聊里面提问题,跳出来耐心回答我的,总是以上三位大神之中的某一个,其实还有另一位梳着辫子的大神也一样耐心,恩,那是Lennart的老大。。。往往我觉得自己还没把自己的问题表达清楚,他们已经理解并且给我提出解决方案了。。。这些大神都在同一个部门,他们的职位都是量化分析师(或者量化分析师的老大),能跟他们打上交道的部门总共也没几个,碰巧当时我就被分配在了其中一个。刚毕业的时候,能在一群科学家呵护下成长,不得不承认是一件非常幸运的事情。半年前,为了抚慰自己不安分的心,跳槽去了另外一个城市的另外一家银行,就再也没有Haskell用了,做新的Java项目的时候我申请用Scala,终于也被驳回了。。。如果再让我选择一次要不要跳槽,我应该还是会选择会,因为到了新的城市之后,我有妹子了(姚明脸)~~----------------------------------------------------------------------------------------------------------------最后,分享一些关键词,来帮助新手快速理解Haskell基本思想,最最最基本的要算是进入正题,要看 然后要理解等价于接着要知道如果愿意深入到哲学层面,可以试着理解我贴得都是中文WIKI,如果觉得不够详尽的话,请自行看英文版。
作为初阶使用者,我猜想所谓精通就是可以从左往右写代码吧……
我是没本事来回答这问题的,我只是说说感想。当我看到“精通Python是一种怎样的体验”的时候,我很高兴地点进来想看看牛逼的人是怎么样的。当我看到“精通C++是一种怎样的体验”的时候,我在想这么牛(bian)逼(tai)的人知乎上会有吗?然后我看到本题的时候我就觉得,“精通Haskell是一种怎样的体验”,这真的不是什么逻辑悖论吗?

我要回帖

更多关于 haskell platform 的文章

 

随机推荐