Виды ограничений Haskell - ограничение по умолчанию для реализации по умолчанию

Заголовок: я хотел бы предоставить реализацию по умолчанию для метода класса, параметризованного над ограничением, который использует экземпляр по умолчанию для этого ограничения.

Учтите следующее:

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}

import GHC.Exts (Constraint)

class Foo a where
  type Ctx a :: Constraint
  type Ctx a = Show a

  foo :: (Ctx a) => a -> String
  foo = show

main :: IO ()
main = putStrLn "Compiles!"

Это не скомпилируется с ошибкой:

Could not deduce (Show a) arising from a use of ‘show’
from the context (Foo a)

С моей точки зрения, он должен использовать ограничение по умолчанию Show, который позволил бы это скомпилировать. Есть ли причина, по которой это не работает, или кто-нибудь может предложить хороший способ добиться этого?

1 ответ

Решение

Вы можете добиться этого, используя DefaultSignatures:

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DefaultSignatures #-}

import GHC.Exts (Constraint)

class Foo a where
  type Ctx a :: Constraint
  type Ctx a = Show a

  foo :: (Ctx a) => a -> String

  default foo :: Show a => a -> String
  foo = show

main :: IO ()
main = putStrLn "Compiles!"

С моей точки зрения, он должен использовать ограничение по умолчанию Show, что позволило бы скомпилировать.

Причина, по которой ваш подход не работает, состоит в том, что пользователь вашего класса должен иметь возможность переопределить любое количество значений по умолчанию. Ваш код сломался бы, если бы кто-то попытался переопределить Ctx но нет foo,

Другие вопросы по тегам