【问题标题】:What's the next step to learning Haskell after monads?在monads之后学习Haskell的下一步是什么?
【发布时间】:2010-07-14 14:43:15
【问题描述】:

我一直在逐渐学习 Haskell,甚至觉得自己掌握了一些 monad。但是,还有很多我几乎看不懂的异国情调的东西,比如 Arrows、Applicative 等。虽然我是从我看过的 Haskell 代码中拾取零碎的东西,但最好找到一个真正解释的教程他们完全。 (似乎有几十个关于 monad 的教程......但一切似乎在那之后就完成了!)

【问题讨论】:

  • 你应该看看 Typeclassopedia,它有很多关于 Applicative 和箭头的概念(不确定箭头)。你可以在the monad reader issue 13找到它
  • 忘记异国情调的东西。写代码。只有当您编写了足够多的代码时,您才能体会到更奇特的抽象是如何提供帮助的。即便如此,如果没有 ArrowsApplicative,你很可能会相处得很好:GHC 中有 100k 行代码,我们甚至从不使用单子转换器。
  • @Simon:我理解你的意思,但你真的认为尝试关闭对更高级抽象的好奇心是个好主意吗?我个人并不主要使用 Haskell 来完成工作——我可以在 Java 或 Ruby 中更有效地工作。我使用 Haskell 是因为它给了我新的思考方式。我读到海报的问题是本着这种精神——而不是关于如何“相处得很好”。
  • 我认为他的观点是人们认为“Haskell”并认为“学术抽象”,而不是“编程语言”。当你学习 Haskell 但从未真正编程过任何东西时,循环会继续。 Haskell 是用来编写计算机程序的,而不是用来让你的朋友相信你比他们聪明。
  • @Travis,我担心的是,如果我们给人的印象是你必须学习和理解这些高级概念才能使用它,那么我认为我们可能会让人们远离这种语言,仅此而已。

标签: haskell


【解决方案1】:

在“掌握”单子之后,我发现一些有用的资源:

  • 正如 SuperBloup 所说,Brent Yorgey 的 Typeclassopedia 是必不可少的(事实上它确实涵盖了箭头)。
  • Real World Haskell 中有很多很棒的东西可以被认为是“在 monad 之后”:例如应用解析、monad 转换器和 STM。
  • John Hughes 的 "Generalizing Monads to Arrows" 是一个很好的资源,它教会了我关于 monad 的知识和关于箭头的知识一样多(尽管我认为我在阅读时已经理解了 monad)。
  • "Yampa Arcade" 论文很好地介绍了函数响应式编程。
  • 关于类型族:我发现使用它们比阅读它们更容易。 vector-space 包是一个起点,或者您可以查看 Oleg Kiselyov 和 Ken Shan 的 course on Haskell and natural language semantics 的代码。
  • 从 Chris Okasaki 的 Purely Functional Data Structures 中挑选几章并详细阅读。
  • Raymond Smullyan 的 To Mock a Mockingbird 是对组合逻辑的极易理解的介绍,它将改变您编写 Haskell 的方式。
  • 阅读 Gérard Huet 的Functional Pearl on zippers。代码是 OCaml,但在处理此类论文时,将 OCaml 翻译成 Haskell 很有用(而且不太难)。

最重要的是,深入研究您发现自己使用的任何 Hackage 库的代码。如果他们使用您不理解的语法、习语或扩展名做某事,请查一下。

【讨论】:

  • 我希望我能收藏你的答案。
  • 这些都是很好的资源,但我认为冈崎的书可能是最基础的,也是最直接有用的。
  • 这里有很多很棒的链接,谢谢!也感谢其他人的回答:)
  • 谢谢@kylc!我已经修复了答案中的链接。
【解决方案2】:

关于类型类:

  • Applicative 实际上比Monad 更简单。我最近在其他地方说过a few things about it,但要点是它是关于增强的Functors,您可以将功能提升到其中。要了解Applicative,您可以尝试使用Parsec 编写一些东西而不使用do 表示法——我的经验是,对于简单的解析器来说,应用风格比单子风格更有效。 p>

  • Arrows 是一种非常抽象的处理类似于函数的事物(类型之间的“箭头”)的方式。除非您偶然发现自然是Arrow-like 的东西,否则它们可能很难引起您的注意。有一次,我在编写带有反馈循环的交互式状态机时,重新发明了一半的 Control.Arrow(效果不佳)。

  • 你没有提到它,但是一个经常被低估的强大类型类是不起眼的Monoid。有很多地方可以找到类半体结构。例如,看看monoids package


除了类型类,我会为您的问题提供一个非常简单的答案:编写程序!最好的学习方式是边做边学,所以选择一些有趣或有用的东西,然后让它发生.

事实上,许多更抽象的概念——比如Arrow——如果你稍后再看它们并发现它们像我一样为你遇到的问题提供了一个简洁的解决方案,可能会更有意义遇到但还没意识到可以抽象出来。

但是,如果您想拍摄特定的东西,为什么不看看Functional Reactive Programming--这是一个很有前途的技术系列,但是对于什么是最好的,还有很多悬而未决的问题这样做的方法是。

【讨论】:

  • +1 用于从Monad 备份到ApplicativeFunctorMonoid,我建议以相反的顺序(从Monoid 开始)。 然后重新访问 Monad 并查看Arrow。我敢打赌,您最终会更好地理解Monad,以便将其置于更广泛的背景中。 Monad 附有很多神奇的想法。它只是另一个类型类,即接口加代数定律。
  • @Conal:这个答案已经有一年多了,如果有什么我事后想改变的话,那就是更加强调Monoid。它可能是最简单的结构,真正展示了代数思维的力量,还有很多其他的东西是根据幺半群的变化来定义的。我想我实际上会把CategoryFunctorApplicative 放在一起,尽管稍后会留下Arrow
  • 感谢Category的提醒。我在那里和你在一起。简单而通用。
【解决方案3】:

MonadApplicativeArrowFunctor 这样的类型类非常棒,甚至更能改变你对代码的看法,而不是使用泛型函数带来的便利。但是有一个普遍的误解,认为 Haskell 的“下一步”是学习更多的类型类和构建控制流的方法。下一步是决定你想写什么,并尝试写它,一路探索你需要什么。

即使您了解 Monad,也并不意味着您已经了解了可以使用 monad 结构化代码执行的操作。使用解析器组合库,或编写自己的。探索为什么应用符号有时对他们来说更容易。探索为什么限制自己使用应用解析器可能更有效。

查看逻辑或数学问题并探索实现回溯的方法——深度优先、广度优先等。探索 ListT 与 LogicT 和 ChoiceT 之间的区别。看看延续。

或者做一些完全不同的事情!

【讨论】:

    【解决方案4】:

    您可以做的最重要的事情就是探索更多的 Hackage。处理 Haskell 的各种奇特功能可能会让您找到某些问题的改进解决方案,而 Hackage 上的库将极大地扩展您的工具集。

    关于 Haskell 生态系统的最佳部分是,您可以在学习外科精确的新抽象技术与学习如何使用 Hackage 上可用的巨型电锯之间取得平衡。

    【讨论】:

      【解决方案5】:

      开始编写代码。您将在学习过程中学习必要的概念。

      除了语言之外,要有效地使用 Haskell,您还需要学习一些现实世界的工具和技术。需要考虑的事项:

      • Cabal,用于管理依赖项、构建和部署 Haskell 应用程序的工具*
      • FFI(外来函数接口)使用 Haskell 代码中的 C 库**
      • Hackage 作为他人库的来源。
      • 如何profile and optimize
      • 自动测试框架(QuickCheck、HUnit)。

      *)cabal-init 有助于快速启动。

      **) 目前,我最喜欢的 FFI 绑定工具是bindings-DSL

      【讨论】:

        【解决方案6】:

        作为一个下一步(而不是六个“下一步”),我建议您学习编写自己的类型类。这里有几个简单的问题可以帮助您入门:

        • 为 QuickCheck 编写一些有趣的实例声明。例如,假设您想生成某种“有趣”的随机树。

        • 继续下面的小问题:定义函数/\\/complement(“and”、“or”和“not”),这些函数不仅可以应用于布尔值但对于任意数量的谓词。 (如果你仔细看,你可以在 SO 上找到这个问题的答案。)

        【讨论】:

          【解决方案7】:

          您知道编写代码所需的一切。但是,如果您正在寻找更多的 Haskell 知识来学习,我建议您:

          • 类型族。非常方便的功能。它基本上为您提供了一种在类型级别上编写函数的方法,当您尝试以非常精确的方式编写参数是多态的函数时,这很方便。一个这样的例子:

          data TTrue = TTrue
          data FFalse = FFalse

          class TypeLevelIf tf a b where 键入 If tf a b 奇怪的IfStatement :: tf -> a -> b -> tf a b

          instance TypeLevelIf TTrue a b where 类型 If TTrue a b = a 奇怪的IfStatement TTrue a b = a

          instance TypeLevelIf FFalse a b where 键入 If FFalse a b = b 奇怪的IfStatement FFalse a b = a

          这为您提供了一个行为类似于if 语句的函数,但能够根据给出的真值返回不同的类型。

          如果您对类型级编程感到好奇,类型族提供了一种进入该主题的途径。

          • Haskell 模板。这是一个巨大的课题。它为您提供类似于 C 中宏的功能,但类型安全性更高。

          • 了解一些领先的 ​​Haskell 库。我数不清有多少次 parsec 使我能够快速编写一个非常有用的实用程序。 dons 定期发布关于 hackage 的流行库列表; check it out.

          【讨论】:

            【解决方案8】:

            【讨论】:

              【解决方案9】:

              写一个haskell编译器:-)。

              【讨论】:

                猜你喜欢
                • 2017-06-04
                • 2014-01-10
                • 2012-01-31
                • 1970-01-01
                • 2011-07-20
                • 1970-01-01
                • 1970-01-01
                • 2021-08-25
                • 1970-01-01
                相关资源
                最近更新 更多