【问题标题】:Type of any in Haskell?Haskell中的任何类型?
【发布时间】:2017-09-29 14:09:06
【问题描述】:

我最近开始尝试通过阅读 LearnYouAHaskell 和互联网上的随机文章来学习 Haskell。

我很难理解更复杂的函数类型。

一些我理解的例子。

> :t map  
map :: (a -> b) -> [a] -> [b]

它接受一个函数(接受 a 并给出 b,即 a 和 b 可以是不同的类型)和一个 a 的列表并返回一个 b 的列表。

> :t fst  
fst :: (a, b) -> a

接受 2 个元素的元组(允许不同的类型)并返回第一个。

> :t any  

在更高的层次上,我理解any。它接受一个函数和一个列表,如果任何列表条目对该特定函数返回 true,则返回 true。我也在 Python 和 JavaScript 中使用过它。

问题

  • 我不明白any :: Foldable t => (a -> Bool) -> t a -> Bool 是如何翻译成上述内容的。

    • (a -> Bool) 是谓词。接受一个参数并返回真或假。
    • t a -> Bool Bool 是 any 的最终结果。根据我的理解 t 和 a 代表谓词和列表。为什么它们不被-> 分开?
  • 如何从总体上理解类型签名以及如何深入挖掘以便我可以自己接近它们?

【问题讨论】:

    标签: haskell types type-signature


    【解决方案1】:
    any :: Foldable t => (a -> Bool) -> t a -> Bool
    

    这里Foldable t 表示t 是类型类Foldable 的一个实例。

    Foldable 是一个类型类,如果类型t 是类型类Foldable 的一个实例,我们可以从签名的t a 部分或从类型类Foldable 的定义中知道, t 实际上是一个类型构造函数。

    所以t a 是一个类型,因此t a -> Bool 是一个函数,它将t a 类型的值映射到Bool。这个函数将是闭包,它将 将谓词应用于t a 类型值的每个“元素”,直到找到一个,在谓词下产生True,或者它没有找到返回TrueFalse 在各自的情况。 (实际的实现可能会有很大的不同。)

    例如[] 是类型类Foldable 的一个实例,因此t a 可以是某物的列表。在这种情况下,我们也可以写成[a],而不是[] a

    但还有其他类型的构造函数,可以是Foldable 的实例,例如某些种类的树。

    【讨论】:

    • 谢谢。类型类不是像(Eq a) 那样封闭吗?
    • 如果只有一个类型类,可以省略函数签名中的paran.. parenth.. ()thingies。
    • +1 指出[a] 只是将类型构造函数[] 应用于类型变量a 的一种特殊形式,这使得将文字值[] 替换为变量t 更容易理解。
    【解决方案2】:

    请注意until recently, the signature was actually

    any :: (a -> Bool) -> [a] -> Bool
    

    这在the Foldable Traversable in Prelude proposal 期间得到了概括:现在值的容器不必是列表,也可以是例如array:

    Prelude> import qualified Data.Vector as Arr
    Prelude Arr> :set -XOverloadedLists
    Prelude Arr> let a = [1,2,3] :: Arr.Vector Int
    Prelude Arr> any (>2) a
    True
    

    【讨论】:

    • 第一个签名好可读。感谢您指出。
    【解决方案3】:

    类型签名是函数的标记名称,指示要处理的类型以及如何部分应用函数。

    Foldable t => (a -> Bool) -> t a -> Bool
    

    Foldable t 首先说any 函数可以使用任何数据类型,它是可折叠类型类的实例。

    第一个参数(a -> Bool) 显然是一个函数,它从我们的可折叠数据类型中获取单个元素(a)并返回一个Bool 类型值。这是JavaScript中.some(callback)的回调。当您将此参数应用于any 时,您将返回一个类型的函数;

    t a -> Bool

    现在我们只剩下一个函数,它只接受一个参数并返回一个Bool 类型(TrueFalse)值。同样t a 是一种数据类型,它是可折叠类型类的成员。它可以是[],但也可以是Tree,前提是数据类型在可折叠的实例下定义了foldMap 函数。它是 JavaScript 的 myArr.some(callback) 中的 myArr 部分,只是它不必是数组。

    【讨论】:

    • 有道理:-)
    【解决方案4】:

    t a 没有被-> 分隔,因为t a 是可折叠的实例,例如:List a 或 Tree a。让我们回到map 一会儿。您提供的版本专门用于列表;一个更通用的版本(作为历史的意外,在大多数 Haskell 版本中称为fmap)的类型为fmap :: Functor f => (a->b) -> f a -> f b。您在此签名中的输入列表在哪里?这是f a。现在,返回到any t a 是第二个参数,您要折叠的 Foldable 的实例,列表或树或其他任何东西。

    您将了解到 Haskell 中的所有函数实际上只有 1 个参数,我们在这里看到了这一点。 any 接受它的第一个参数(谓词)并返回一个函数,该函数接受一个可折叠的(列表、树等)并返回一个 Bool

    【讨论】:

      【解决方案5】:

      t a 不代表谓词和列表。正如您之前已经正确指出的那样,(a -> Bool) 是谓词。 t a 只代表列表,但它不一定是列表(这就是为什么它是 t a 而不是 [a])。 t 可以是任何可折叠的,所以它可以是[],但也可以是其他一些集合类型或Maybe

      【讨论】:

      • 有道理。谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多