Functor / Applicative 可以绑定到一种特定类型或结构吗?

Can a Functor / Applicative be tied to one specific type or structure?

我正在尝试理解应用类型类,尤其是 <*> 函数。现在我看到它的类型签名是 f (a -> b) -> f a -> f b 并且我认为 f 是一个仿函数,我认为它是某种包装一些数据的结构。在我看来 f 必须处理泛型类型,特别是 f 必须有参数化类型 a、[=16] =],其实也必须支持a -> b

如果我的理解是正确的,那么我们正在做的是使用类型类 f ,它最初旨在包装一些数据,比如字符串列表或包含文件缓冲区的树或任何随机的我们可能想要的东西。但是f一定不能提交给任何一种类型,因为它不仅要处理这样一种类型,而且还需要处理从一个数据到另一个数据的函数。因此,如果我们有一个 <*> 的示例实现,其中包含

Just2 f <*> j = fmap f j

读这个的方法是 jJust2 内部的某种数据。 f 是一个将数据映射到数据的函数。 f 包裹在 Just2.

这些都对吗?从根本上说,我的问题是:任何应用程序都必须如此通用,以至于它总是可以同时处理任意数据,并且还可以从数据到数据运行吗?或者有什么方法可以使应用程序内部允许的唯一数据是列表?

对于 "regular" Functors 和 Applicatives,你是对的;他们需要能够处理任何类型的值。这被称为 参数多态性 。如果你有一个你认为几乎是 Functor 的类型,除了它不能那样做,然后考虑 mono-traversable 包中的 the MonoFunctor typeclass。它与 Functor 的想法相同,只是内置了一个有效的元素类型。我不知道有任何包具有等同于 Applicative 的单态。我认为这是因为 <*> 在同一个容器中使用了 3 种不同类型的值,所以它没有很好的单态模拟。

是的,你的理解基本正确。特别是,任何特定的 Applicative,比如一个名为 Foo 的函数,都具有函数 pure 的关联特化,类型签名为:

pure :: a -> Foo a

必须适用于调用者选择的任何类型 a,例如:

> pure 10 :: Foo Int
> pure length :: Foo (String -> Int)

因此,无论 Foo 是什么,它都必须能够 "handle" 任何提供的类型而不受限制,因为 pure 在技术上可以不受限制地应用于任何类型。

但要注意一点。函子 f "wraps" 数据的想法,因此 f Int 在某种程度上是 Int 值的 "container",可以是一个有用的直觉,并且通常是字面上正确的(例如,列表、树等),但这并不总是严格正确的。 (一些反例包括函子 IO(->) rConst b,它们 "contain" 的值与真实容器的意义非常不同。)

从你的问题来看,似乎可能有许多不同的 Applicative 类型类。但是只有一个;因此它必须是通用的。

应用类型类由其函数(<*>pure)以及这些函数需要遵守的法则定义。在任何 Haskell 代码库中,只能有一个定义。但是可以有许多类型 具有 应用类型类的实例。您可以使用 instance 声明并通过定义所需的函数来定义自己的实例。不过,编译器不会检查您的定义是否遵守仿函数法则 - 这取决于您。

Type类 像 Functor、Applicative 和 Monad 不指定数据类型;他们并没有说你需要一个 "list-like" 类型,或者一个 "box-like" 类型,事件虽然列表和其他容器如 Either 确实有这些类型的实例 类。任何类型,你可以以适用法则适用的方式配备所需的功能,成为应用。

想到容器或盒子通常会很有帮助。但是一旦你使用像函数这样的类型的应用实例,你就需要扩展这种直觉;例如,a -> r.

与面向对象语言中的接口相比,类型类更强大,因为即使您无法访问该类型的源代码,您也可以将某些数据类型定义为类型类的实例本身。