- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
(我希望这个问题是切中主题的——我尝试寻找答案,但没有找到明确的答案。如果这恰好偏离主题或已经得到回答,请审核/删除它。 )
我记得曾多次听到/读过关于 Haskell 是最好的命令式语言的半开玩笑的评论,这当然听起来很奇怪,因为 Haskell 通常以其功能性而闻名 功能。
所以我的问题是,Haskell 的哪些品质/特性(如果有的话)有理由证明 Haskell 被视为最佳命令式语言 - 或者它实际上更像是一个笑话?
最佳答案
我认为这半真半假。 Haskell 具有惊人的抽象能力,其中包括对命令式想法的抽象。例如,Haskell 没有内置的命令式 while 循环,但我们可以直接编写它,现在它可以了:
while :: (Monad m) => m Bool -> m () -> m ()
while cond action = do
c <- cond
if c
then action >> while cond action
else return ()
这种抽象级别对于许多命令式语言来说都是困难的。这可以用具有闭包的命令式语言来完成;例如。 Python 和 C#。
但 Haskell 还具有(高度独特的)能力,可以使用 Monad 类来描述允许的副作用。例如,如果我们有一个函数:
foo :: (MonadWriter [String] m) => m Int
这可能是一个“命令式”函数,但我们知道它只能做两件事:
它无法打印到控制台或建立网络连接等。结合抽象能力,您可以编写作用于“产生流的任何计算”等的函数。
Haskell 的抽象能力使其成为一种非常优秀的命令式语言。
然而,错误的一半是语法。我发现 Haskell 非常冗长并且难以以命令式方式使用。这是使用上面 while
的命令式计算示例循环,查找链表的最后一个元素:
lastElt :: [a] -> IO a
lastElt [] = fail "Empty list!!"
lastElt xs = do
lst <- newIORef xs
ret <- newIORef (head xs)
while (not . null <$> readIORef lst) $ do
(x:xs) <- readIORef lst
writeIORef lst xs
writeIORef ret x
readIORef ret
所有 IORef 垃圾、双重读取、必须绑定(bind)读取结果、fmapping ( <$>
) 来操作内联计算的结果......这一切看起来都非常复杂。从功能的角度来看,这很有意义,但命令式语言往往会隐藏大部分细节,以使它们更易于使用。
诚然,也许如果我们使用不同的 while
-风格的组合器会更干净。但是,如果您将这种哲学运用得足够远(使用一组丰富的组合器来清楚地表达自己),那么您将再次达到函数式编程。命令式 Haskell 并不像设计良好的命令式语言那样“流畅”,例如 python 。
总之,通过语法改进,Haskell 很可能是最好的命令式语言。但是,根据整容的本质,它将用外部美丽和虚假的东西取代内部美丽和真实的东西。
编辑:对比 lastElt
用这个Python音译:
def last_elt(xs):
assert xs, "Empty list!!"
lst = xs
ret = xs.head
while lst:
ret = lst.head
lst = lst.tail
return ret
行数相同,但每行的噪音要少得多。
<小时/>编辑2
就其值(value)而言,Haskell 中的纯粹替换看起来是这样的:
lastElt = return . last
就是这样。或者,如果你禁止我使用 Prelude.last
:
lastElt [] = fail "Unsafe lastElt called on empty list"
lastElt [x] = return x
lastElt (_:xs) = lastElt xs
或者,如果您希望它适用于任何 Foldable
数据结构并认识到您实际上并不需要 IO
处理错误:
import Data.Foldable (Foldable, foldMap)
import Data.Monoid (Monoid(..), Last(..))
lastElt :: (Foldable t) => t a -> Maybe a
lastElt = getLast . foldMap (Last . Just)
与Map
,例如:
λ➔ let example = fromList [(10, "spam"), (50, "eggs"), (20, "ham")] :: Map Int String
λ➔ lastElt example
Just "eggs"
(.)
运算符是 function composition .
关于haskell - 为什么 Haskell(有时)被称为 "Best Imperative Language"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6622524/
我接受过 lisp 语言家族的一些培训,现在我为了我自己的利益学习一点 Haskell。在 lisp 中,函数式风格还可以,但有一些情况命令式风格对于获得良好的性能是必要的,例如 追加 Append
我对 react 以及函数式、命令式、声明式等术语都是新手。我发现纯函数很容易测试。我自学使用 Javascript 进行编程。到目前为止,它正在工作,但我的目标是学习编写干净且可维护的代码。我的问题
这个问题是连续尝试克服 appDebugAssemble 失败构建的四天漫长而痛苦的旅程的结果。我已经阅读了大量的主题/文章,这些主题/文章是谷歌通过查找任何带有“multidex”一词但无济于事的东
我有一个关于编程和英语语言的问题:在评论单行代码时是使用第三人称还是命令式。 假设在命令式语言中的以下代码行应该被注释: object.doSomething(); 我评论这一行的方法是使用第三人称将
我是 Scala 新手,刚刚阅读 Scala By Example 。在第2章中,作者有2个不同版本的快速排序。 一种是命令式: def sort(xs: Array[Int]) { def
我看到在 Java 中有两种方式来转换一个对象: List l = new ArrayList(); ArrayList first = (ArrayList) l; ArrayList second
假设在 C 中,我们有以下结构: struct MyData { char key1[20]; long key2; ... /* some data */ }; 本质上,除
我正在创建一个继承自 NamedTuple 的类(特别是为了不变性)元组中包含三部分数据。我正在覆盖 __repr__()提供一个漂亮的、人类可识别的类表示。然而,自定义__repr__必须对元组中的
我有以下 reducer 功能: reducer 的第一个 参数是聚合值,第二个 参数是下一个值。下面的 reducer 函数减少了相同的 reaction 参数,但聚合了 state$ 值。每个 r
(我希望这个问题是切中主题的——我尝试寻找答案,但没有找到明确的答案。如果这恰好偏离主题或已经得到回答,请审核/删除它。 ) 我记得曾多次听到/读过关于 Haskell 是最好的命令式语言的半开玩笑的
我已经为我的 添加了一个事件监听器到我的自定义元素中打电话。 问题 Is there a shorter (more convenient syntax) way to imperatively (
我正在设计一种命令式语言,但在实现循环功能时遇到了问题。循环将采用以下形式: Do (n Loop Body 我可以正确地解析循环,但是在评估循环时,会出现两个问题。第一个是我不
我想和一些老东西一起玩 Collatz conjecture并决定以(非常)函数式的风格来做它会很有趣,所以我实现了一个 unfoldr 函数,接近 Haskell has 函数。 : fn unfo
在 Polymer 2.0 ( https://www.polymer-project.org/2.0/docs/devguide/events#imperative-listeners ) 的新文档
在下面的示例中,我有一个调用子自定义元素的父自定义元素。子项具有可在父级 CSS 中定义的 p 元素的可变 color CSS 属性。 在子元素的JS中,想读取父元素处选择的--custom-colo
我是一名优秀的程序员,十分优秀!