Lisp vs Haskell 选哪一个入手? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zuozuo
V2EX    问与答

Lisp vs Haskell 选哪一个入手?

  •  
  •   zuozuo 2013-05-27 17:07:17 +08:00 13701 次点击
    这是一个创建于 4552 天前的主题,其中的信息可能已经有所发展或是发生改变。
    想学习一下涵式编程 Lisp 和 Haskell 选择哪个更适合一些?
    18 条回复    1970-01-01 08:00:00 +08:00
    G2bN4dbX9J3ncp0r
        1
    G2bN4dbX9J3ncp0r  
       2013-05-27 19:00:24 +08:00   1
    为啥不两个都看一下
    levn
        2
    levn  
       2013-05-27 19:10:03 +08:00
    看你对括号的忍耐程度
    insraq
        3
    insraq  
       2013-05-27 19:58:49 +08:00
    Scala is more pragmatic, although it's not pure functional
    someFork
        4
    someFork  
       2013-05-27 20:02:32 +08:00
    不要学 Haskell,yinwang 说得清楚了。
    benyur
        5
    benyur  
       2013-05-27 20:12:17 +08:00
    果断lisp
    Golevka
        6
    Golevka  
       2013-05-27 20:17:18 +08:00
    Standard ML
    duhastmich
        7
    duhastmich  
       2013-05-27 20:19:34 +08:00
    lisp 要简单很多, 一般推荐scheme吧

    @someFork 不要学Haskell?愿闻其详
    davepkxxx
        9
    davepkxxx  
       2013-05-27 20:38:33 +08:00
    Haskell 为了函数式而函数式,ML系都有点这个感觉。
    duhastmich
        10
    duhastmich  
       2013-05-27 20:41:03 +08:00   1
    @Perry 博主说了他在扯淡好不好:) haskell 我就懂点毛皮,博主说的效率问题我不清楚,他也没说不要学haskell,lazy evaluation 的概念是我学haskell的重要收获之一
    Perry
        11
    Perry  
       2013-05-27 20:46:34 +08:00   1
    @duhastmich 恩,yinwang在 http://www.yinwang.org/blog-cn/2013/04/17/languages/ 也提到了haskell的启发。
    zuozuo
        12
    zuozuo  
    OP
       2013-05-27 21:57:01 +08:00
    @lidashuang 嗯,说的也是,现在正在看haskell,看这个主要是想学涵式编程,然后打算看一下List主要是因为我之前一直是写ruby的,想看看ruby到底从Lisp里面学了哪些东西。
    zuozuo
        13
    zuozuo  
    OP
       2013-05-27 22:03:34 +08:00
    @duhastmich 嗯,lazy evaluation 确实是一个很有启发性的概念,在 ruby2.0里面也加入了lazy的特性:
    [1,2,3].lazy.cycle.take(7).to_a #=> [1, 2, 3, 1, 2, 3, 1]
    someFork
        14
    someFork  
      2013-05-28 01:37:28 +08:00   2
    王垠:不再推荐 Haskell


    在之前的一篇博文里,我推荐从函数式语言入手掌握程序语言。推荐的两种语言是 Scheme 和 Haskell。可是出于多种原因,我必须告诉大家,我已经不再推荐 Haskell。这里的原因比较深入,可能不容易说清楚,所以只简述一下。如果有异议的话,可以来信跟我讨论,这样也可以帮我理清思路。

      先说说之前推荐 Haskell 的原因吧。推荐它其实是因为是它的类型关系较 Scheme 清晰,并且有模式匹配等方便的功能。可是类型系统和模式匹配,却不是 Haskell 所专有的。其它的一些语言,比如 OCaml 和 Racket 也有很方便的模式匹配和能力相近的类型系统。

      现在停止推荐 Haskell,其实是出于很多原因的积累:

      1. 类型系统过于复杂

      最开头的时候,Haskell 使用的是普通的 Hindley-Milner 类型系统(HM 系统)。使用这种类型系统的原因是因为程序员不需要写任何类型标记(typeannotation)就可以“静态”的确保类型的正确。可是这样做的代价是,这个类型系统表达能力太弱。很多程序需要拐弯抹角的绕过这个类型系统的种种限制才写得出来。比如,Haskell 的 sum type 导致 constructor 的非常麻烦的多重嵌套,这我已经在一篇英文博文里面比较隐晦的批评了一下。显然 HM 系统灵活性太差,所以 Haskell 内部后来引进了 SystemFw。可是这些系统发展了好多年,还是不能解决问题。到现在,你仍然会在 Haskell 里面遇到莫名其妙的限制。你觉得程序应该编译通过,可是它就是编译不过(比如我这篇英文博客所述)。究其原因,其实是类型系统有问题,而不是程序员的思路有问题。

      有的 Haskell 程序员可能会反驳,说是因为我不能理解 Haskell 的类型系统。那么我可以告诉你,我不但实现了 Haskell 和 ML 所用的 HM 系统,而且实现了比 HM 还要强大的 MLF, intersection type 等类型系统。Haskell 推导不出来的类型,我的系统可以推导出来。所以我说的话其实是出自第一手的依据。

      2. 参数和返回值的类型标记很有必要

      与 Haskell 同门的 SML 和 OCaml 的类型系统也有类似的问题,甚至更加严重(比如 ML 有 value restriction,导致不必要的约束和困惑)。但是很多“常规语言”,特别是像 Java,C++ 等需要类型标记的语言,却没有这个问题。很多人喜欢 Haskell 都是因为用它可以“不写类型标记”,可是现在呢,最好的 Haskell 程序员都是先把类型写下来,才开始写函数。一来这样思路清晰,你知道这函数要处理哪些类型的数据,你就明确的把它写下来,以后再来看,或者给其他人看,都一目了然。二来是因为 Haskell 的类型系统由于加入的一些“不可判定”(undecidable)的扩展功能,有时候已经无法推导出类型了。而给函数的参数和返回值加上类型标记之后,就可以轻松推导出类型。所以你看到,给参数和返回值加上类型标记,不管是对人还是对机器,都有好处。所以经过我一学期的研究得出的结论是,HM 系统的类型推导,其实是多此一举。

      不过需要注意的是,函数的局部变量,其实是不需要类型标记的。比如在 Java 程序里常见的:

      List<String> ls = newArrayList<String>();

      这样的赋值语句,其实是没必要在左边加一个类型标记的,因为右边的类型我们知道。在这一点上C++11 的 "auto" 是一个正确的方向。比如在 C++11 里,你可以写:

      auto ls =newArrayList<String>();

      这种类型推导不难做,基本就是一个抽象解释器。我给 Python 做的 PySonar 类型推导系统里面就实现了这样的功能。

      对任何语言,具体是哪些地方有必要加上类型标记呢?其实有一个很简单的方法来判断:观察信息进出函数的“接口”,把这些接口都做上标记。直观一点说,函数就像是一个电路模块,只要我们知道输入和输出是什么,那么中间的导线里面是什么,我们其实都可以推出来。类型推导的过程,就像是模拟这个电路的运行。这里函数的输入就是参数,输出就是返回值,所以基本上把这两者加上类型标记,里面的局部变量的类型都可以推出来。另外需要注意的是,如果函数使用了全局变量,那么全局变量就是函数的一个“隐性”的输入,所以如果程序有全局变量,都需要加上类型标记。

      3. “纯函数式”并不是好主意

      我最近常常跟同学开玩笑,说“纯函数式”语言是什么意思。“纯函数式”语言是用来描述这样一个世界的,在这个世界里,所有的东西都是“有线”的(wired)。不存在 3G,4G,不存在 wifi,收音机,卫星电视…… 所谓的 monads,其实就是这个布满电缆的世界里的“接线盒”。

      Haskell 编程之麻烦,就是因为这些电缆。你必须小心翼翼的把它们接在一起,安排好,否则就会有各种问题,甚至绊到脚。连生成随机数这么简单的事情,你都得学会使用各种各样的“随机数 monads”。这是因为我们需要记录随机数发生器的“状态”,所以随机数 monad 输入一个随机数发生器,返回一个随机数以及一个新的随机数发生器!想一想,在 C 语言里面,你只需要一个全局变量或者函数内部的 static 变量来记录随机数发生器的状态。到底是谁简单,谁复杂?我想你可能已经意识到,全局变量其实就是 wifi!

      Haskell 的支持者常说,纯函数的语言容易“推理”,容易确保程序的正确。因为它的程序就像“数学的函数”,给同一个输入,就会得到同一个输出。这叫做“referentialtransparency”。可是这种性质,真的可以让程序容易“推理”吗?如果 Haskell 的函数使用了 monads,比如“状态”(statemonad),那么这个函数的“输入”,就几乎永远不会相同。因为那个状态每次都可能变化,所以你实际上还是没法知道那里面是什么!

      记住这一点:世界上没有包治百病的神药。

      4. 惰性求值(lazyevaluation)不是好主意

      关于惰性求值,我基本同意 Robert Harper 的观点。惰性求值让类型变得混乱,让程序的时间和空间复杂度难以分析,而且跟并行计算的原则有根本性的矛盾。而惰性求值的功能,却不是经常有用的。即使需要,在普通的语言里也可以通过 thunk 来实现。所以,惰性求值带来的问题恐怕比它解决的问题还要多。

      很多自称“从 Haskell 衍生”的语言,很多其实都只是有其形,而无其实。一个例子就是 Bluespec,一种硬件描述语言。它虽然自称是从 Haskell 演变来的,看起来像 Haskell,但是它却不是惰性的,类型系统也很简单,所以基本上它已经不是 Haskell。打着 Haskell 的旗号,恐怕是想借助 Haskell 的名声来抬高自己,或者是因为 Bluespec 的创造者 Lennart Augustsson 最早的时候是 Haskell 的主要发起人之一。

      5. 思想局限

      所以综上所述,Haskell 自称的“特性”几乎被实践一一推翻。可是 Haskell 程序员往往炫耀自己的“函数式编程”水平,其实经常陷入一些很难理解的“设计模式”,无法自拔。鉴于这个原因,我停止向大家推荐 Haskell。

      另外需要申明一下的是,我停止推荐 Haskell 并不是因为我想力推 Scheme。实际上 Scheme 也有自己的问题,但是相对来说,它更加简单易懂,符合学习的需要。另外,以前对 C 和 C++ 的批评也许过于偏激。最近为了在 LLVM 上做一些事情,开始重新理解C++,发现它做的好些事情其实是挺不错的,甚至超过好些最炫的,带有“dependenttype”的函数式语言。所以现在我觉得,其实世界上的语言并没有什么绝对的标准。在一段时间认为是错的东西,可能却是对的。所以不用盲目的排斥一些语言,把它们都拿来看一下,互相对比,才会知道到底什么是好的。
    zuozuo
        15
    zuozuo  
    OP
       2013-05-28 01:40:51 +08:00
    @someFork "所以不用盲目的排斥一些语言,把它们都拿来看一下,互相对比,才会知道到底什么是好的。" 这个说得很好,很赞同,学习不同的语言然后互相对比还能加深对各个语言特性的理解。
    momo5269
        16
    momo5269  
       2013-05-28 02:28:02 +08:00
    看你对括号的忍耐程度 +1
    y
        17
    y  
       2013-05-28 04:10:44 +08:00
    @momo5269
    @levn 不能忍受括号的两位,你们的编辑器是高亮加粗括号的么……
    括号淡淡地放在那里就可以了,好的编辑器输入左括号就会出右括号的,按个键就跳出括号。
    momo5269
        18
    momo5269  
       2013-05-28 04:19:57 +08:00
    @y调侃而已 Racket之类的自动完成是做得很好的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5269 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 09:12 PVG 17:12 LAX 01:12 JFK 04:12
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86