【问题标题】:Making Vector.Generic an instance of Functor (and other type-classes使 Vector.Generic 成为 Functor 的实例(和其他类型类
【发布时间】:2011-10-27 16:17:15
【问题描述】:

我在尝试将 Vector.Generic.Vector 设为其他类型类的实例时遇到了麻烦(在我的例子中是 Functor)。

我可以满足于向 Vector.Unboxed.Vector 添加一个 Functor 实例,但我也想不出它的语法。 我最好的做法是尝试以下方法:

instance (U.Unbox a, U.Unbox b) => Functor U.Vector where
    fmap = U.map

但是编译器(公正地)抱怨“a”和“b”在“=>”之后的任何地方。 我什至可以为 Functor 做这个定义,因为它假设 fmap 允许采用的类型有更多限制?

我在 SO 中发现的大多数东西都太高级了,我无法弄清楚,所以请温柔 :-)

【问题讨论】:

    标签: haskell typeclass


    【解决方案1】:

    想想fmap的类型:

    fmap :: Functor f => (a -> b) -> f a -> f b
    

    您正在尝试添加ab 都是Unbox 的实例的约束。这是不可行的,因为fmap 是完全通用的,而未装箱的Vector 的地图特定于实例Unbox

    不能设为Functor

    【讨论】:

      【解决方案2】:

      monadic 是正确的,这在 haskell 中目前是不可能的。然而,目前 ghc head 开发分支中的一个新语言特性将使这成为可能。

      该功能称为约束种类,并且(以及其他功能)允许您向类添加索引约束。类的实例可以决定需要什么约束。如果实例未声明,则可以提供默认约束。

      例如,Functor 类可以这样重写:

      class Functor m where
        type FunctorCtxt f a :: Constraint
        type FunctorCtxt f a = ()
        fmap :: (FunctorCtx f a, FunctorCtx f b) => f a -> f b
      

      诸如 for 列表和 Maybe 等现有实例将保持不变 - 没有给出默认上下文(任何类型变量都可以接受)。你可以为 Vector 实例添加一个新的约束:

      instance Functor U.Vector where
          type FunctorCtxt U.Vector a = U.Unbox a
          fmap = U.map
      

      更多详情请见Constraint Kinds for GHC blog postKindFact GHC wiki post

      请注意,我的计算机上没有安装 ghc head,所以我无法测试这是否真的有效。

      【讨论】:

      • 谢谢,这很有趣。但是,我目前不喜欢使用最前沿的功能(而且,正如 monadic 指出的那样,我试图做一些与 Functor 的基本定义相冲突的事情)
      • 当然,使用仅存在于开发分支中的功能风险太大,尤其是使用编程语言(他们可以在正确发布之前更改语法/语义)。不过,这是将来要研究的事情。
      猜你喜欢
      • 2019-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-07
      • 1970-01-01
      相关资源
      最近更新 更多