为什么 (*3) `map` (+100) 在 Idris 中不起作用?

Why doesn't (*3) `map` (+100) work in Idris?

在 Haskell 中,函数是仿函数,以下代码按预期工作:

(*3) `fmap` (+100) $ 1

输出当然是303。但是,在 Idris 中(使用 fmap -> map),它给出了以下错误:

Can't find implementation for Functor (\uv => Integer -> uv)

在我看来,函数在 Idris 中似乎没有作为函子实现,至少不像在 Haskell 中那样,但这是为什么呢?

此外,类型签名 (\uv => Integer -> uv) 到底是什么意思?它 看起来 像一些部分应用的函数,这是仿函数实现所期望的,但是语法有点混乱,特别是应该使用的 \因为 lambda/literal 正在那里做。

仿函数是一个接口。在 Idris 中,实现仅限于数据或类型构造函数,即使用 data 关键字定义。我不是依赖类型方面的专家,但我相信这个限制是必需的——实际上,至少——对于一个健全的接口系统。

当你在 REPL 中询问 \a => Integer -> a 的类型时,你会得到

\a => Integer -> a : Type -> Type

在Haskell中我们会认为这是一个真正的类型构造函数,它可以成为类类型的实例,例如Functor。然而,在 Idris 中,(->) 不是类型构造函数,而是 binder.

最接近您在 Idris 中的示例的是

((*3) `map` Mor (+100)) `applyMor` 1

使用 Data.Morphisms 模块。或者一步一步来:

import Data.Morphisms

f : Morphism Integer Integer
f = Mor (+100)

g : Morphism Integer Integer
g = (*3) `map` f

result : Integer
result = g `applyMor` 1

这是有效的,因为 Morphism 是一个真正的类型构造函数,在库中定义了一个 Functor 实现。