我在尝试使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中发现的大多数东西都太难以让我弄清楚,所以请温柔: - )
答案 0 :(得分:8)
考虑fmap
的类型:
fmap :: Functor f => (a -> b) -> f a -> f b
您正尝试添加a
和b
都是Unbox
实例的约束。这是不可行的,因为fmap
完全是一般的,而未装箱的Vector
的地图特定于实例Unbox
。
不能成为Functor
。
答案 1 :(得分:4)
monadic是正确的,这在haskell目前是不可能的。然而,ghc head development分支中目前的新语言功能将使这成为可能。
该功能称为Constraint Kinds,并且(在其他功能中)允许您向类添加索引约束。类的实例可以决定需要什么约束。如果实例未声明一个,则可以提供默认约束。
例如,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
诸如列表和Maybe
之类的现有实例将保持不变 - 给出一个默认的无关上下文(任何类型变量都是可接受的)。您可以为Vector实例添加新约束:
instance Functor U.Vector where
type FunctorCtxt U.Vector a = U.Unbox a
fmap = U.map
详情请见Constraint Kinds for GHC blog post和KindFact GHC wiki post。
请注意,我的计算机上没有安装ghc head,所以我无法测试这是否真的有效。