【问题标题】:Why is Haskell fully declarative?为什么 Haskell 是完全声明式的?
【发布时间】:2016-10-19 11:20:47
【问题描述】:

我不太了解命令式声明式编程范式之间的区别。我读到 Haskell 是一种声明性语言。在某种程度上,我会说是的,但在命令式的定义方面有一些事情让我感到困扰。

当我有一个数据结构并使用 Haskell 的函数进行转换时,我实际上只是告诉了要转换的内容。所以我把数据结构作为一个函数的参数,对结果很满意。

但是如果没有真正满足我需求的功能呢?

我将开始编写一个自己的函数,该函数期望数据结构作为参数。之后,我将开始编写应该如何处理数据结构。由于我只能调用本机 Haskell 函数,我仍然使用声明性范式,对吗?但是当我开始使用“if 语句”时会发生什么。既然我要告诉程序如何从那时起做事,这难道不会结束声明性吗?

【问题讨论】:

  • 对于它的价值,我总是发现“命令式”/“声明式”的区别也有点人为。我发现还有其他更客观的描述:Haskell 是纯粹的、惰性的和强静态类型的,在我看来,每一个都是重要的支柱。
  • 在我理解了标题为术语的线程之后,我想我会向后倾斜并保持同样的想法......但首先我需要许可! :P
  • 这是我写的一篇文章,它可能会让您更好地理解代码声明性的含义。 TL;DR 是声明性代码不描述过程中的步骤,它使不变量、保证或真相声明。 medium.com/@danielt1263/…

标签: haskell declarative


【解决方案1】:

也许这是一个观点问题。在我看来,根据其他事物来定义事物并没有什么必要,因为我们总是可以用它的定义替换某些东西(只要定义是纯粹的)。也就是说,如果我们有f x = x + 1,那么我们看到f z 的任何地方都可以替换为z + 1。因此,纯函数不应真正被视为指令;它们应该被视为定义。

出于这个原因,很多 Haskell 代码被认为是声明性的。我们简单地将事物定义为其他事物的(纯)函数。

也可以在 Haskell 中编写命令式代码。有时我们真的很想说“做A,然后做B,然后做C”。这为函数应用的简单世界增加了一个新维度:我们需要一个“发生在之前”的概念。 Haskell 采用 Monad 概念来描述具有评估顺序的计算。事实证明这非常方便,因为它可以封装改变状态等效果。

【讨论】:

  • 所以 monad 是一种 Haskell 语言功能,它实际上结束了命令式的声明方式?
  • @xetra11 monad 是一个可以描述顺序过程的数学概念。在 Haskell 中,它只是一个类型类,碰巧以语法糖(do notation)的形式提供了一些语言支持。
  • @xetra11 虽然“ends”这个词太强了——毕竟Monad 只是另一个类型类,正如 user2297560 提醒我们的那样——我们可以说 monads can 用于以声明的方式表达命令性。不过,正如 chepner 的回答所强调的那样,可以说,与实际代码相比,命令性更多地存在于我们的脑海中。
【解决方案2】:

Haskell 中没有if 语句,只有if 表达式 if a then b else c,这实际上相当于类似C 语言中的a ? b : cb if a else c 这样的三元表达式在 Python 中。你不能省略else,它可以在任何可以使用任意表达式的地方使用。进一步限制a 必须具有Boolean 类型,并且bc 必须具有相同类型。它是语法糖

case a of
  True -> b
  False -> c

不要太拘泥于“声明性”这个标签;它只是该语言支持的一种风格 编程。例如,考虑阶乘函数的典型声明式定义:

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

这也只是你认为更重要的东西的语法糖:

fact n = case n of 
          0 -> 1
          otherwise -> n * fact (n - 1)

【讨论】:

  • 所以你可以说它就像另一个返回“this”或“that”的函数。您能否添加一个示例,如果它离开声明性范式,它会是什么样子?我可以在这里使用伪代码。如果这个例子势在必行的话,看看 Haskell 应该允许什么是非常棒的。
  • @xetra11 是的,if 完全可以是一个有 3 个参数的函数,不会有什么不同。
  • @chepner 最后一个匹配模式的例子真的很重要吗?因为它是一个表达式:|
【解决方案3】:

坦率地说,“声明式编程”这个术语更像是一个营销术语。它意味着“指定做什么,而不是如何做”的非正式定义是模糊的,可以解释,而且绝对远离黑白界限。在实践中,它似乎适用于广泛属于函数式编程、逻辑编程或使用领域特定语言 (DSL) 类别的任何事物。

因此(我意识到这可能不符合您的问题的答案,但仍然:)),我建议您不要浪费时间去想知道某些东西是否仍然是声明性的。命令式编程、函数式编程和逻辑编程这两个术语已经更有意义了,所以也许反思一下这些术语会更有用。

【讨论】:

  • 是的,我发现自己挖得很深,我想我不会完全满意
【解决方案4】:

声明式语言由表达式构成,而命令式语言由语句构成。

通常的解释是做什么怎么做。你已经发现了其中的困惑。如果你这样理解,声明式使用定义(按名称),而命令式使用定义。那么什么是声明性语言?一个只命名定义的?如果是这样,那么您可以编写的唯一 Haskell 程序就是 main

有一种声明方式和一种命令方式有分支,它直接来自定义。声明式分支是表达式,命令式分支是语句。 Haskell 有case … of …(一个表达式),C 有if (…) {…} else {…}(一个语句)。

表达式和语句有什么区别?表达式有值,而语句有效果。值和效果有什么区别?

对于表达式,有一个函数μ 将任何表达式e 映射到它的值μ(e)。这也称为语义,或含义,理想情况下是定义良好的数学对象。这种定义值的方式称为指称语义。还有其他方法。

对于语句,在语句 S 之前有一个状态 P,在语句 S 之后有一个状态 Q。 S 的效果是从 P 到 Q 的增量。这种定义效果的方式称为 Hoare 逻辑。还有其他方法。

【讨论】:

  • 所以当使用核心语义是 preStatepostStateeffect 语句时,我要搬进来势在必行的情况?虽然使用表达式是一种声明方式,因为我可以自己声明结果而无需调用函数(fun x = x + 1 与使用 1 作为资源并仅声明它是2,因为这与使用前面提到的纯函数时的表达式结果相同)
  • 如果是表达式就是声明性的。 1 + 1fun 12 都是整数 2 的表达式。正如其他人指出的,“声明式”和“命令式”有多种用法;我的目标是提供一种具有精确含义的用途。表达式可能还有其他品质。如果表达式 E 由子表达式 M 组成,并且如果任何表示与 M 相同的值的表达式 N 可以代替 M 而不会改变 E 的含义,则 N 在 E 中是引用透明 . 换句话说,重要的是你说什么而不是你怎么说
  • 我希望拒绝投票要求此人发表评论。
【解决方案5】:

你不能在 Haskell 中使用“if 语句”,因为没有。您可以使用“if 表达式”

if c then a else b

但这只是像

这样的语法糖
let f True a b = a; f False a b = b in f c a b  

这又是完全声明性的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 2015-12-17
    相关资源
    最近更新 更多