haskell - 使函数成为向量类型类的实例

标签 haskell types typeclass

我有一个用于数学向量的自定义类型类

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}

class Vector v a where

    infixl 6 <+>
    (<+>) :: v -> v -> v  -- vector addition

    infixl 6 <->
    (<->) :: v -> v -> v  -- vector subtraction

    infixl 7 *>
    (*>)  :: a -> v -> v  -- multiplication by a scalar

    dot   :: v -> v -> a  -- inner product

我想制作数字a和功能 a -> vector进入类的一个实例。数字很​​简单:
instance Num a => Vector a a where
    (<+>) = (+)
    (<->) = (-)
    (*>)  = (*)
    dot   = (*)

我认为函数也很容易(好吧,除了 dot ,但我可以忍受)
instance Vector b c => Vector (a -> b) c where
    f <+> g = \a -> f a <+> g a
    f <-> g = \a -> f a <-> g a
    c *>  f = \a -> c *> f a
    dot     = undefined

但是,我收到以下错误:
Ambiguous type variable `a0' in the constraint:
  (Vector b a0) arising from a use of `<+>'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: f a <+> g a
In the expression: \ a -> f a <+> g a
In an equation for `<+>': f <+> g = \ a -> f a <+> g a

我如何告诉 GHC 该实例对所有类型都有效 a ?我应该在哪里添加类型签名?

最佳答案

类型族绝对是解决这个问题的最好方法

{-# LANGUAGE TypeFamilies, FlexibleContexts #-} 
class VectorSpace v where
    type Field v

    infixl 6 <+>
    (<+>) :: v -> v -> v  -- vector addition

    infixl 6 <->
    (<->) :: v -> v -> v  -- vector subtraction

    infixl 7 *>
    (*>)  :: Field v -> v -> v  -- multiplication by a scalar

    dot   :: v -> v -> Field v  -- inner product

从数学上讲,要使用函数创建向量空间,您必须重用相同的字段:
instance VectorSpace b => VectorSpace (a -> b) where
    type Field (a -> b) = Field b
    f <+> g = \a -> f a <+> g a
    f <-> g = \a -> f a <-> g a
    c *>  f = \a -> c *> f a
    dot     = error "Can't define the dot product on functions, sorry."

...关于类型族的好处是它们的工作方式与您解释的方式非常相似。
让我们做两个向量空间的直接乘积:
instance (VectorSpace v,VectorSpace w, Field v ~ Field w,Num (Field v)) => VectorSpace (v,w) where
    type Field (v,w) = Field v
    (v,w) <+> (v',w') = (v <+> v',w <+> w')
    (v,w) <-> (v',w') = (v <-> v',w <-> w')
    c *> (v,w) = (c *> v, c*> w)
    (v,w) `dot` (v',w') = (v `dot` v') + (w `dot` w')

您可以替换 Num具有自定义代数类的上下文,但 Num捕捉概念
一个领域的适度好。

关于haskell - 使函数成为向量类型类的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13029532/

相关文章:

list - 当我们已经有了列表时,为什么 Haskell 需要 Data.Sequence?

haskell - 是否可以反转类型对齐的遍历?

swift - 你能在 swift 中强制执行类型别名吗

python - 为什么一些 numpy 数据类型是 JSON 可序列化的,而另一些则不是?

haskell - Monoid vs MonadPlus

multithreading - IORef 和 MVar 有什么区别?

haskell - 从 Haskell 中的数据中获取值

python - 使用 `is (CustomClass)` 可以安全地检测 Python 中的未初始化值

Scala vs Haskell 类型类 : "catchall" instances

haskell - 在父类(super class)函数的定义中使用子类实现