声明用于N个N个元素矩阵与N个元素列向量相乘的类型类 [英] Declaring a type class for multiplication of an N-by-N-element matrix and an N-element column vector
问题描述
在Haskell中,如果您具有类型的族"(例如,对于N的某些值,则为N个元素的矩阵)和相关"类型的并行族(例如,N个元素的向量) ,对于相同的N值),以及需要每个族中一种特定类型的操作(例如,将N×N元素矩阵与N元素列向量相乘),则可以声明类型该操作的课程?
In Haskell, if you have a "family" of types (say, N-by-N-element matrices, for some values of N), and a parallel family of "related" types (say, N-element vectors, for the same values of N), and an operation that requires one specific type from each family (say, multiplying an N-by-N-element matrix and an N-element column vector), is it then possible to declare a type class for that operation?
对于这个特定的示例,我想它看起来像这样:
For this specific example, I imagine it would look something like this:
class MatrixNxN m where
--| Multiplication of two N-by-N-element matrices
mmul :: Num a => m a -> m a -> m a
--| Multiplication of an N-by-N-element matrix and an N-element column vector
vmul :: Num a => m a -> v a -> v a
但是,我不知道如何限制类型v
.可以做这样的事情吗?
I don't know how to constrain the type v
, however. Is it possible to do something like this?
请注意,我既欢迎对声明多个相关类型的类型类的一般问题的解答,也对为矩阵向量乘法声明类型类的特定问题的解答表示欢迎.在我的特定情况下,只有一小部分已知的N值(2、3和4),但是我通常对理解Haskell的类型系统中可能进行编码的内容感兴趣.
Please note that I welcome both answers to the general question of declaring a type class of multiple, related types, as well as answers to the specific question of declaring a type class for matrix-vector multiplication. In my specific case, there is only a small, known set of values of N (2, 3, and 4), but I'm generally interested in understanding what is possible to encode in Haskell's type system.
编辑:我使用 MultiParamTypeClasses
实施了此操作和 FunctionalDependencies
,如下面的加布里埃尔·冈萨雷斯(Gabriel Gonzalez)和MFlamer所建议.这就是我实现的相关部分最终看起来像什么:
I implemented this using MultiParamTypeClasses
and FunctionalDependencies
as suggested by Gabriel Gonzalez and MFlamer below. This is what the relevant bits of my implementation ended up looking like:
class MatrixVectorMultiplication m v | m -> v, v -> m where
vmul :: Num a => m a -> v a -> v a
data Matrix3x3 a = ...
data Vector3 a = ...
instance MatrixVectorMultiplication Matrix3x3 Vector3 where
vmul = ...
这是vmul
的类型签名,它本身并已部分应用:
This is the type signature of vmul
, on its own and partially applied:
vmul :: (Num a, MatrixVectorMultiplication m v) => m a -> v a -> v a
(`vmul` v) :: Matrix3x3 Integer -> Vector3 Integer
(m `vmul`) :: Vector3 Integer -> Vector3 Integer
我觉得这一切都很优雅.感谢您的回答! :)
I find this all very elegant. Thanks for the answers! :)
推荐答案
这是对MFlamer
答案的很小的改动,这也使得m
依赖于v
:
This is a very tiny variation on MFlamer
's answer, which also makes m
dependent on v
:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
class MatrixNxN m v | m -> v, v -> m where
mmul :: Num a => m a -> m a -> m a
vmul :: Num a => m a -> v a -> v a
那样,如果您这样做:
(`vmul` someVector)
...,则编译器可以仅根据someVector
的类型选择正确的实例.
... then the compiler can select the correct instance on the basis of someVector
's type alone.
类型族解决方案由于相同的原因而无法工作,主要是因为如果您声明v
类型构造函数为m
类型构造函数的类型函数,则该类型函数不一定是1-to- 1,因此编译器将无法从v
推断m
.这就是为什么人们说功能依赖比类型族更强大的原因.
The type family solution won't work for the same reason, mainly because if you declare the v
type constructor to be a type function of the m
type constructor, that type function is not necessarily 1-to-1, so the compiler wouldn't be able to infer m
from v
. This is why people say that functional dependencies are more powerful than type families.
这篇关于声明用于N个N个元素矩阵与N个元素列向量相乘的类型类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!