2016-05-22 4 views
1

У меня есть тип данных для матриц, определяемых как 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, но это не удается с очевидным «Не удалось вывести ... из контекста» ошибка, которая, как ожидается, как я не определить мой pad чтобы покрыть все возможные значения b.

Любые предложения здесь?

ответ

2

Мне кажется, что обе версии пэдов делают концептуально разные вещи, поэтому у них, вероятно, также должны быть разные имена. Не всегда полезно определять класс типа, когда вы заметили какой-то видимый шаблон в коде.

Это говорит ... Вы можете сделать как попытку с 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

Подпись

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 <<") 
Смежные вопросы