使函数成为矢量类型类的一个实例 [英] Make functions an instance of vector type class
问题描述
我有一个用于数学向量的自定义类型类
$ $ p $ {code> { - #LANGUAGE MultiParamTypeClasses,FlexibleInstances# - }
class Vector va其中
infixl 6 +
(< +>):: v - > v - > v - 矢量添加
infixl 6 - < - >
(< - >):: v - > v - > v - 矢量减法
infixl 7 *>
(*>):: a - > v - > v - 乘以标量
dot :: v - > v - > a - 内部产品
我想让数字 a
和函数 a - > vector
到类的一个实例中。数字很简单:
实例Num a =>向量aa其中
(+)=(+)
( - )=( - )
(*>)=(*)
点=(*)
我认为函数也很容易(除了<$ c
$ p $ 实例Vector bc =>向量(a - > b)c其中
f + g = \ a - > f a + g a
f< - > g = \ a - > f a< - > g a
c *> f = \ a - > c *> fa
dot = undefined
然而,我得到以下错误:
约束中的歧义类型变量`a0':由于使用'+'引起的
(向量b a0)
可能的修复:添加修复这些类型变量的类型签名
在表达式中:fa&+> g a
在表达式中:\ a - > f a + g a
在'+'的等式中:f + g = \ a - > f a + ga
如何告诉GHC该实例对全部类型有效 A
?在哪里我应该添加类型签名?
类型系列绝对是解决这个问题的最可爱的方式
{ - #LANGUAGE TypeFamilies,FlexibleContexts# - }
class VectorSpace v其中
类型字段v
infixl 6 +
(< +>):: v - > v - > v - 矢量添加
infixl 6 - < - >
(< - >):: v - > v - > v - 矢量减法
infixl 7 *>
(*>):: Field v - > v - > v - 乘以标量
dot :: v - > v - > Field v - 内部产品
在数学上,为了使函数中的向量空间不用,必须重用同样的字段:
实例VectorSpace b => VectorSpace(a - > b)其中
类型字段(a - > b)=字段b
f + g = \ a - > f a + g a
f< - > g = \ a - > f a< - > g a
c *> f = \ a - > c *> f a
dot =错误无法定义函数上的点积,抱歉。
...关于类型系列的好处在于,它们的工作方式非常多,您将如何解释。
我们做两个向量空间的直接结果:
pre $ $ $ $ $ $ $>实例(VectorSpace v,VectorSpace w,Field v_Field w,Num(字段v))=> VectorSpace(v,w)其中
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`disk`v')+ `dot` w')
您可以替换 Num
context与一个自定义的代数类,但 Num
适当地捕获了字段的概念
。
I have a custom type class for mathematical vectors
{-# 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
and I want to make numbers a
and functions a -> vector
into an instance of the class. Numbers are easy:
instance Num a => Vector a a where
(<+>) = (+)
(<->) = (-)
(*>) = (*)
dot = (*)
and I thought functions would also be easy (well, except for dot
, but I can live with that)
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
However, I get the following error:
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
How can I tell GHC that the instance is valid for all types a
? Where am I supposed to add the type signature?
Type families are definitely the loveliest way of solving this problem
{-# 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
Mathematically, to make a vector space out of functions, you have to reuse the same field:
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."
...and the nice thing about type families is that they work very much how you would explain. Let's make the direct product of two vector spaces:
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')
You could replace the Num
context with a custom algebraic class, but Num
captures the concept
of a Field moderately well.
这篇关于使函数成为矢量类型类的一个实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!