【问题标题】:Can smart-constructor types have multiple valid Functor instances?智能构造函数类型可以有多个有效的 Functor 实例吗?
【发布时间】:2020-05-14 22:56:30
【问题描述】:

关于Functors 的这两条规则相当有名:

  1. 如果类型参数以逆变方式出现,则无法创建 Functor
  2. 任何类型最多有一个有效的Functor 实例

但如果你稍微作弊,你就可以打破第一条规则。以休斯列表为例:

data HList a = UnsafeHList ([a] -> [a])

pattern HList a <- UnsafeHList (($ []) -> a)
    where HList a = UnsafeHList (a ++)

instance Functor HList where
    fmap f (HList a) = HList (map f a)

-- instances necessary to make HList useful, but irrelevant to this example, have been omitted

只要您假设所有HLists 都将通过智能构造函数生成,那么Functor 实例是合法的,即使a 出现逆变。

我的问题:你可以使用类似的技术来打破第二条规则吗?如果您假设它们总是通过智能构造函数生成,是否有任何类型具有两个不同的有效 Functor 实例?

【问题讨论】:

  • (ehem) 顺便说一句,你可以通过使用米田来制作差异列表功能而不作弊:newtype HList a = HList (forall b. (a -&gt; b) -&gt; [b] -&gt; [b])
  • @luqui 那似乎确实有效并且具有良好的渐近性。我想知道为什么与智能构造方法相比,它没有更受欢迎。
  • (co)yoneda 是一个很好的将事物功能化的技巧,被低估了。也许是因为它有一个可怕的名字(以前从未阻止过我们......)

标签: haskell constructor typeclass functor parametric-polymorphism


【解决方案1】:

当然。假设你有

newtype Foo a = Foo Bool

mkFoo = Foo True

这是它的两个Functor 实例:

instance Functor Foo where
  fmap _ (Foo x) = Foo x

instance Functor Foo where
  fmap _ !_ = mkFoo

【讨论】:

  • 是的,毕竟这看起来是合法的,尽管出于某种原因它仍然让人不满意。
  • "at most one valid Functor instance" 假设是合法的实例,这可能就是它感觉不令人满意的原因。
  • “智能构造函数”限制阻止您观察布尔值,这使得该实例在观察上等同于显而易见的实例。基本上,它们还是一样的。
  • 我不确定这是否完全正确。我认为类型实际上不仅仅是一种类型,而且是我们选择在该类型上使用的等价。 Foo 可以用两个等价“完成”:它可以有两个不同的值或只有一个。在第一种情况下,“const”实例无效。在第二种情况下,“identity”和“const”实例都是有效的,但是......它们也是相等的。是否有一个类型(由 both 实际的 Haskell 类型 我们想要在其上使用的等价物定义)实际上有两个有效的、不等价的(通过该等价物)@987654325 @ 实例?
  • @HTNW,我非常怀疑,但我不确定如何证明这一点。一个无效的Functor 实例必须通过参数化违反身份法。将类型的值视为代表可以解决这个问题。所以我们需要修复仍然违反组成法。我认为这意味着您的抽象无法忠实地映射到任何 Haskell类型,这似乎相当难以置信。
猜你喜欢
  • 1970-01-01
  • 2017-11-07
  • 1970-01-01
  • 1970-01-01
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-20
相关资源
最近更新 更多