首页 文章

Haskell或标准ML适合初学者? [关闭]

提问于
浏览
72

我将在离散结构中教一个低级课程 . 我选择了教科书Discrete Structures, Logic, and Computability部分是因为它包含有助于使用函数式编程语言实现的示例和概念 . (我也认为这是一本很好的教科书 . )

我想要一个易于理解的FP语言来说明DS概念以及学生可以使用的 . 大多数学生最多只能用一到两个学期的Java编程 . 在查看Scheme,Erlang,Haskell,Ocaml和SML之后,我已经确定了Haskell或Standard ML . 由于下面列出的原因,我倾向于Haskell,但我喜欢那些在一个或那个中活跃的程序员的意见 .

  • Haskell和SML都有模式匹配,这使得描述递归算法变得简单 .

  • Haskell有很好的列表推导,可以很好地匹配这些列表以数学方式表达的方式 .

  • Haskell有懒惰的评价 . 非常适合使用列表理解技术构建无限列表 .

  • SML有一个真正的交互式解释器,可以在其中定义和使用函数 . 在Haskell中,函数必须在单独的文件中定义,并在交互式shell中使用之前进行编译 .

  • SML在语法中明确地确认了函数参数和返回类型,'s easy to understand. For example: val foo = fn : int * int -> int. Haskell'的隐式咖喱语法有点迟钝,但并非完全陌生 . 例如:foo :: Int - > Int - > Int .

  • Haskell默认使用任意精度的整数 . 它是SML / NJ中的外部库 . 并且SML / NJ默认将输出截断为70个字符 .

  • Haskell 's lambda syntax is subtle -- it uses a single backslash. SML is more explicit. Not sure if we' ll在这个类中需要lambda .

从本质上讲,SML和Haskell大致相同 . 我倾向于Haskell,因为我喜欢Haskell中的列表理解和无限列表 . 但我担心Haskell紧凑语法中的大量符号可能会导致学生出现问题 . 从我收集到的关于SO的其他帖子开始,Haskell不建议初学者从FP开始 . 但我们不打算构建成熟的应用程序,只是尝试简单的算法 .

你怎么看?


编辑:在阅读了一些很好的回复后,我应该澄清一些我的要点 .

在SML中,在解释器中定义函数和在外部文件中定义函数之间没有语法上的区别 . 假设您要编写阶乘函数 . 在Haskell中,您可以将此定义放入文件中并将其加载到GHCi中:

fac 0 = 1
fac n = n * fac (n-1)

对我来说,这很清楚,简洁,并且符合书中的数学定义 . 但是如果你想直接在GHCi中编写函数,你必须使用不同的语法:

let fac 0 = 1; fac n = n * fac (n-1)

在使用交互式口译员时,从教学角度来看,当学生在文件和命令行中使用相同的代码时,非常非常方便 .

通过"explicit confirmation of the function,"我的意思是,在定义函数时,SML立即告诉您函数的名称,参数的类型和返回类型 . 在Haskell中你必须使用 :type 命令,然后你会得到一些有点令人困惑的咖喱符号 .

关于Haskell的一个更酷的事情 - 这是一个有效的函数定义:

fac 0 = 1
fac (n+1) = (n+1) * fac n

同样,这与他们可能在教科书中找到的定义相匹配 . 在SML中无法做到这一点!

8 回答

  • 2

    我们在大学的第一年教Haskell . 我对此的看法有点混乱 . 一方面教Haskell到头几年意味着他们不必忘记命令式的风格 . Haskell也可以生成非常简洁的代码,以前有过Java的人可以欣赏它们 .

    我注意到学生经常遇到的一些问题:

    • 模式匹配起初可能有点困难 . 学生最初在看到 Value 构建和模式匹配是如何相关时遇到了一些问题 . 他们在区分抽象方面也存在一些问题 . 我们的练习包括编写简化算术表达的函数,一些学生很难看到抽象表示(例如 Const 1 )和元语言表示( 1 )之间的差异 .

    此外,如果您的学生应该自己编写列表处理功能,请注意指出模式之间的差异

    []
    [x]
    (x:xs)
    [x:xs]
    

    根据您想要在途中教授多少函数式编程,您可以给它们一些库函数,让它们随意使用它们 .

    • 我们没有教我们的学生匿名功能,我们只是告诉他们 where 条款 . 对于某些任务,这有点冗长,但其他方面效果不错 . 我们也没有告诉他们部分申请;这可能很容易在Haskell中解释(由于它的写入类型),所以它可能值得向他们展示 .

    • 他们很快就发现了列表推导,并将它们优先于高阶函数 filtermapzipWith .

    • 我想我们错过了教他们如何让他们按类型引导他们的想法 . 不过,我不太确定这对初学者是否有帮助 .

    • 错误消息通常对初学者没有多大帮助,他们偶尔可能需要一些帮助 . 我没有't tried it myself, but there'是一个专门针对新手的Haskell编译器,主要是通过更好的错误消息:Helium

    • 对于小型程序,可能的空间泄漏等问题不是问题 .

    总的来说,Haskell是一种很好的教学语言,但有一些陷阱 . 鉴于学生对列表推导感觉比高阶函数更舒服,这可能是您需要的论据 . 我不知道你的课程有多长,或者你想教他们多少编程,但是要花些时间教他们基本概念 - 他们需要它 .

  • 4

    哈斯克尔 . 我是如此全面的语言,它会教你大量的CS,只需使用它 .

    但是,SML更容易学习 . Haskell具有惰性评估和控制结构等功能,使其功能更强大,但成本却是陡峭(ish)的学习曲线 . SML没有这样的曲线 .

    也就是说,Haskell的大部分内容都来自于较少科学/数学语言,如Ruby,ObjC或Python .

  • 8

    我很惊讶你不考虑OCaml和F#,因为它们解决了你的许多问题 . 当然,体面和有益的开发环境是学习者的首要任务吗?在这方面,SML远远落后于所有其他FPL .

    此外,OCaml和F#都有列表推导 .

  • 83

    就像我喜欢Haskell一样,以下是我更喜欢SML用于离散数学和数据结构(以及大多数其他初学者类)的类的原因:

    • 即使对于专家来说,Haskell程序的时间和空间成本也很难预测 . SML提供了更有限的方式来吹制机器 .

    • 交互式解释器中的函数定义语法与文件中使用的语法相同,因此您可以剪切和粘贴 .

    • 虽然SML中的运算符重载完全是假的,但它也很简单 . 在不必进入类型类的情况下,很难在Haskell中教授整个类 .

    • 学生可以使用 print 进行调试 . (虽然,正如评论者指出的那样,使用 Debug.Trace.trace 可以在Haskell中获得几乎相同的效果 . )

    • 无限的数据结构打动了人们的思想 . 对于初学者来说,最好让他们定义一个带有ref单元格和thunk的流类型,这样他们就知道它是如何工作的:

    datatype 'a thunk_contents = UNEVALUATED of unit -> 'a
                               | VALUE of 'a
    type 'a thunk = 'a thunk_contents ref
    val delay : (unit -> 'a) -> 'a thunk
    val force : 'a thunk -> 'a
    

    现在它不再是魔法了,你可以从这里到流(无限列表) .

    • 布局不像Python那么简单,可能会令人困惑 .

    Haskell有两个优势:

    • 在核心Haskell中,您可以在定义之前编写函数的类型签名 . 这对学生和其他初学者非常有帮助 . 在SML中处理类型签名并不是一种好方法 .

    • Haskell具有更好的具体语法 . Haskell语法是对ML语法的重大改进 . 我写了一个short note about when to use parentheses in an ML program;这有点帮助 .

    最后,有一把剑可以削减两种方式:

    • Haskell代码默认是纯粹的,所以你的学生不太可能偶然发现不纯的结构(IO monad,state monad) . 但出于同样的原因,他们无法打印,如果你想做I / O然后在最低限度,你必须解释 do 符号,并且 return 令人困惑 .

    在相关主题上,这里有一些关于课程准备的建议:不要忽视Chris Okasaki的Purely Functional Data Structures . 即使您没有让学生使用它,您也一定要复印一份 .

  • 28

    大多数答案都是技术性的,但我认为你应该考虑至少一个不是:Haskell(作为OCaml),在这个时候,有一个更大的社区在更广泛的背景下使用它 . 还有一个大型的图书馆和应用程序数据库,以便在Hackage获取利润和乐趣 . 这可能是让您的学生在课程结束后使用该语言的一个重要因素,也许可以在以后尝试其他功能语言(如标准ML) .

  • 7

    顺便说一句,

    #SML有一个真正的交互式解释器,可以在其中定义和使用函数 . 在Haskell中,函数必须在单独的文件中定义,并在交互式shell中使用之前进行编译 .

    不准确 . 使用GHCi:

    Prelude> let f x = x ^ 2
    Prelude> f 7
    49
    Prelude> f 2
    4
    

    在haskell.org edu上,Haskell在教育方面也有很好的资源 . 页面,来自不同老师的经验 . http://haskell.org/haskellwiki/Haskell_in_education

    最后,如果你使用Haskell,你将能够教他们多核并行,只是为了好玩:-)

  • 13

    SML有一个真正的交互式解释器,可以在其中定义和使用函数 . 在Haskell中,函数必须在单独的文件中定义,并在交互式shell中使用之前进行编译 .

    虽然拥抱可能有这个限制,GHCi不:

    $ ghci
    GHCi, version 6.10.1: http://www.haskell.org/ghc/  :? for help
    Loading package ghc-prim ... linking ... done.
    Loading package integer ... linking ... done.
    Loading package base ... linking ... done.
    Prelude> let hello name = "Hello, " ++ name
    Prelude> hello "Barry"
    "Hello, Barry"
    

    我喜欢GHC(i)而不是Hugs的原因有很多,这只是其中之一 .

    SML以易于理解的语法明确确认函数参数和返回类型 . 例如:val foo = fn:int * int - > int . Haskell的隐式咖喱语法有点迟钝,但并非完全陌生 . 例如:foo :: Int - > Int - > Int .

    SML也有你所谓的“隐式咖喱”语法 .

    $ sml
    Standard ML of New Jersey v110.69 [built: Fri Mar 13 16:02:47 2009]
    - fun add x y = x + y;
    val add = fn : int -> int -> int
    

    基本上,SML和Haskell大致相同 . 我倾向于Haskell,因为我喜欢Haskell中的列表理解和无限列表 . 但我担心Haskell紧凑语法中的大量符号可能会导致学生出现问题 . 从我收集到的关于SO的其他帖子开始,Haskell不建议初学者从FP开始 . 但我们不打算构建成熟的应用程序,只是尝试简单的算法 .

    我喜欢使用Haskell比SML更多,但我仍然会先教SML .

    • 借调nominolo的想法,列表理解确实会让学生放慢一些高阶函数的速度 .

    • 如果你想要懒惰和无限列表,明确地实现它是有益的 .

    • 因为热切地评估了SML,所以执行模型更容易理解,并且"debugging via printf"比Haskell更好地工作 .
      反正

    • SML 's type system is also simpler. While your class likely wouldn' T选用它们,Haskell的类型类仍然是一个多余的突起拿到过 - 让他们了解 'a''a 在SML的区别是不够强硬 .

  • 10

    许多大学将Haskell教授为第一种功能语言甚至是第一种编程语言,因此我认为这不会成为一个问题 .

    在一门这样的课程上完成了一些教学,我不同意你认识到的可能的混淆 . 早期混淆的最可能的来源是解析由错误布局引起的错误,以及在错误地使用数字文字时关于类型类的神秘消息 .

    我也不同意任何关于Haskell不建议初学者开始使用FP的建议 . 当然,突变的严格语言并不是一种大爆炸方法,但我认为这是一种非常有效的方法 .

相关问题