给出一个函子(或任何类型构造函数)f
,我们可以得到该函子的“版本”,其中不包含其参数值。我们只定义newtype NoArg f = NoArg (f Void)
。例如:
NoArg []
只是一个空列表。NoArg Maybe
没什么。NoArg (Either e)
就是e
。NoArg (Identity)
是Void
。NoArg IO
是一个IO动作,可以永久产生效果(就像服务器一样)。Functor f => NoArg (Free f)
是Fix f
。我的问题是我们是否可以做相反的事情,并创建类型为确实使用其参数的Functor的构造函数。形式上,Arg :: (* -> *) -> (* -> *)
应该这样,即存在术语forall a. Arg f a -> a
或等效的Arg f Void -> Void
。例如:
Arg [] a
是a
类型的非空列表的类型。Arg Maybe a
就是a
。Arg (Either e) a
就是a
。Arg Identity a
就是a
。Arg IO a
您会认为是产生结果的IO操作。但是,由于从IO a
到a
甚至没有Maybe a
的{{1}}中都没有函数,因此可能不是这样。const Nothing
是Functor f => Arg (Free f) a
。我认为Free (Arg f) a
是嵌入在Arg f
中的函子g
的某种“至上”,因此存在一个术语f
。
编辑:我想真实的测试应该是Argful g :: g Void -> Void
与Arg [] a
同构,其中
NomEmpty a
答案 0 :(得分:6)
我怀疑Haskell中是否有解决方案,但是在具有依赖对和相等类型的语言中有一个相当简单的定义。我在下面的伊德里斯工作。
首先,我们说f
函子中的两个元素如果被()
填充后变得相等,则它们的形状相同:
SameShape : Functor f => f a -> f b -> Type
SameShape fa fb = (map (const ()) fa = map (const ()) fb)
Arg f a
的元素是f a
的元素,因此f Void
的元素没有相同的形状。
Arg : (f : Type -> Type) -> Functor f => Type -> Type
Arg f a = (fa : f a ** ((fv : f Void) -> SameShape fa fv -> Void))
**
表示一个从属对,其中右侧的组件可以引用第一个组件。此定义恰好排除了不包含a
的那些值。因此,我们具有所需的属性:
lem : Functor f => Arg f Void -> Void
lem (fv ** p) = p fv Refl
其中Refl
证明map (const ()) fv = map (const ()) fv
。
这不适用于IO
,但我不希望对此有任何明智的定义。