扩展其返回类型的通用方法

时间:2016-05-22 12:22:44

标签: haskell

我将矩阵的数据类型定义为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

然后将StringMatrix a声明为Paddable,但是这显然失败了#34;无法从上下文推断..."错误,因为我没有定义pad函数来涵盖b的所有可能值。

这里有什么建议吗?

2 个答案:

答案 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

其中ba确定。因此,可以使用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 <<")