有没有办法“删除”函子中不存储其参数的部分?

时间:2019-01-15 07:46:32

标签: haskell types functional-programming functor type-constructor

给出一个函子(或任何类型构造函数)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 [] aa类型的非空列表的类型。
  • Arg Maybe a就是a
  • Arg (Either e) a就是a
  • Arg Identity a就是a
  • Arg IO a 您会认为是产生结果的IO操作。但是,由于从IO aa甚至没有Maybe a的{​​{1}}中都没有函数,因此可能不是这样。
  • const NothingFunctor f => Arg (Free f) a
  • 等...

我认为Free (Arg f) a是嵌入在Arg f中的函子g的某种“至上”,因此存在一个术语f

编辑:我想真实的测试应该是Argful g :: g Void -> VoidArg [] a同构,其中

NomEmpty a

1 个答案:

答案 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,但我不希望对此有任何明智的定义。