Haskell Constraint Kinds - default constraint for default implementation
Asked Answered
D

1

5

Headline: I would like to provide a default implementation for a class method parametrised over a constraint, which uses the default instance for that constraint.

Consider the following:

{-# 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!"

This fails to compile with the error of:

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

From my perspective, it should be using the default constraint of Show, which would let this compile. Is there any reason this doesn't work, or can anyone suggest a good way to achieve this?

Daune answered 28/7, 2014 at 14:32 Comment(0)
G
9

You can achieve this using 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!"

From my perspective, it should be using the default constraint of Show, which would let this compile.

The reason your approach doesn't work is that the user of your class should be able to override any number of defaults. Your code would break if someone tried to override Ctx but not foo.

Gatling answered 28/7, 2014 at 14:45 Comment(1)
Sure - but I would expect an instance that overrode Ctx but not foo to refuse to compile. Still, this looks like a good solution!Daune

© 2022 - 2024 — McMap. All rights reserved.