为什么 (*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
实现。
在 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
实现。