在Haskell中,函数是仿函数,以下代码按预期工作:
(*3) `fmap` (+100) $ 1
Run Code Online (Sandbox Code Playgroud)
当然输出是303.但是,在Idris(使用fmap - > map)中,它会出现以下错误:
找不到实现
Functor (\uv => Integer -> uv)
对我来说,似乎函数在Idris中没有实现为函子,至少不像它们在Haskell中那样,但为什么呢?
此外,类型签名究竟(\uv => Integer -> uv)意味着什么?它看起来像是一些部分应用的函数,这就是函数实现所期望的,但语法有点令人困惑,特别\是应该用于lambda/literal的是在那里做什么.
小智 5
函子是一个接口。在 Idris 中,实现仅限于数据或类型构造函数,即使用data关键字定义。我不是依赖类型的专家,但我相信这个限制是必需的——至少实际上——对于一个健全的接口系统。
当您\a => Integer -> a在 REPL 中询问类型 时,您会得到
\a => Integer -> a : Type -> Type
Run Code Online (Sandbox Code Playgroud)
在 Haskell 中,我们会认为这是一个真正的类型构造函数,可以将其制成类型类的实例,例如Functor. 然而,在 Idris 中,(->)它不是类型构造函数,而是binder。
与您在 Idris 中的示例最接近的是
((*3) `map` Mor (+100)) `applyMor` 1
Run Code Online (Sandbox Code Playgroud)
使用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
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为它Morphism是一个真正的类型构造函数,Functor在库中定义了一个实现。