Подтвердить что ты не робот

Перегрузка операторов

Я хочу определить оператор (назовем его +-+), который работает в этом:

if a,b are Char    => a +-+ b = [a][b]
if a,b are Integer => a +-+ b = a+b

Я пробовал:

class Summable a where
    (+-+)       :: a -> a -> b

instance Summable Integer where
    a +-+ b     = a + b

instance Summable Char where
    a +-+ b     = [a] ++ [b]

но я получаю ошибки:

Couldn't match type `b' with `Integer'....
Couldn't match type `b' with `[Char]' ....

Можно ли это сделать? Как?

4b9b3361

Ответ 1

Проблема заключается в том, что переменная типа b не может быть определена из экземпляра, даже если она исправлена. (Имея такую ​​свободную переменную, она требует, чтобы функция возвращала то, что имеет любой тип, т.е. undefined.)

Можете ли вы дать +-+ тип a -> a -> a? Если да, сделайте это. (Но похоже, что это невозможно.)

В противном случае вы можете использовать функциональные зависимости, чтобы экземпляр указывал тип результата или тип семейства, так что одним из атрибутов экземпляра является тип результата.

Для функциональных зависимостей код может выглядеть так:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}

class Summable a result | a -> result where
  (+-+) :: a -> a -> result

instance Summable Char String where
  a +-+ b = [a] ++ [b]

instance Summable Integer Integer where
  a +-+ b = a + b

Для семейств типов это будет выглядеть так:

{-# LANGUAGE TypeFamilies #-}

class Summable a where
  type Result a
  (+-+) :: a -> a -> Result a

instance Summable Char where
  type Result Char = String
  a +-+ b = [a] ++ [b]

instance Summable Integer where
  type Result Integer = Integer
  a +-+ b = a + b

(Спасибо Витусу и Владимиру Матвееву за исправление различных ошибок, которые я сделал!:))