我将矩阵的数据类型定义为Matrix a
。在我的程序中的大多数地方,我将其用作Matrix String
的字符串或Matrix (Matrix a)
的其他矩阵。
我需要编写一个根据某些规则填充矩阵内容的函数。对于字符串矩阵,签名将是:
pad :: Matrix String -> Matrix (Matrix String)
因为每个字符串都被转换为一定大小的矩阵。
对于其中包含其他矩阵的矩阵,函数应为:
pad :: Matrix (Matrix a) -> Matrix (Matrix a)
因为在这种情况下只有内部矩阵的大小正在改变。
有没有办法概括这两个?我试过这个:
class Paddable b => Paddable a where
pad :: a -> Matrix b
然后将String
和Matrix a
声明为Paddable
,但是这显然失败了#34;无法从上下文推断..."错误,因为我没有定义pad
函数来涵盖b
的所有可能值。
这里有什么建议吗?
答案 0 :(得分:2)
在我看来,两个版本的pad都在做概念上不同的事情,所以他们也应该有不同的名字。当您在代码中发现一些明显的模式时,定义类型类并不总是一个好主意。
那就是说......你可以像associated type family一样尝试:
{-# LANGUAGE TypeFamilies, FlexibleInstances #-}
class Paddable (PaddedContent a) => Paddable a where
type PaddedContent a :: *
pad :: Matrix a -> Matrix (PaddedContent a)
instance Paddable String where
type PaddedContent String = Matrix String
pad = ...
instance Paddable (Matrix a) where
type PaddedContent (Matrix a) = Matrix a
pad = ...
答案 1 :(得分:1)
签名是
pad :: Matrix a -> Matrix b
其中b
由a
确定。因此,可以使用functional dependencies:
{-# LANGUAGE FlexibleInstances,
MultiParamTypeClasses,
FunctionalDependencies #-}
data Matrix a = Matrix a deriving Show
class Paddable a b | a -> b where
pad :: Matrix a -> Matrix b
instance Paddable (Matrix a) (Matrix a) where
pad = id -- dummy implementation!
instance Paddable String (Matrix String) where
pad (Matrix str) = Matrix . Matrix $ ">> " ++ str ++ " <<"
然后:
\> pad $ Matrix (Matrix 42)
Matrix (Matrix 42)
\> pad $ Matrix "abc"
Matrix (Matrix ">> abc <<")