Haskell中的任意类型是什么?

3

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

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

这是我能理解的一些例子。

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

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

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

输入一个由两个元素组成的元组(允许不同的类型)并返回第一个元素。

> :t any  

在更高层次上,我理解any。它接受一个函数和一个列表,并在该特定函数的任何列表条目返回true时返回true。我也在Python和JavaScript中使用过它。 问题
  • 我不理解any :: Foldable t => (a -> Bool) -> t a -> Bool是如何转化为上面的内容的。

    • (a -> Bool)是谓词。它接受一个参数并返回true或false。
    • t a -> Bool是任何结果的布尔值。根据我的理解,t和a代表谓词和列表。为什么它们没有用->分隔开?
  • 如何理解类型签名以及如何深入挖掘,以便我可以自己处理它们?

5个回答

12
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)这样封闭的吗? - Abhirath Mahipal
5
如果只有一个类型类,那么在函数签名中可以省略括号。 - typetetris
1
+1 是指出 [a] 只是将类型构造函数 [] 应用于类型变量 a 的特殊形式,这使得用变量 t 替换文字值 [] 更容易理解。 - chepner

10

第一个签名非常易读。感谢您指出。 - Abhirath Mahipal

3

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

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

通过 Foldable,它首先表示任何函数都可以与任何数据类型一起使用,这些数据类型是 Foldable 类型类的实例。

第一个参数 (a -> Bool) 很明显是一个函数,它从我们的 foldable 数据类型中获取单个元素 (a) 并返回一个 Bool 类型值。它是 JavaScript 中 .some(callback) 的回调函数。当您将此参数应用于 any 时,您将获得以下类型的函数:

t a -> Bool

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


有道理 :-) - Abhirath Mahipal

2

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是第二个参数,你正在折叠的可折叠实例,列表、树或其他什么东西。

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


1

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


有道理。谢谢。 - Abhirath Mahipal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接