Haskell约束种类 - 默认实现的默认约束

5

标题:我希望为一个参数化的约束类方法提供默认实现,该实现使用该约束的默认实例。

考虑以下情况:

{-# 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个回答

9
您可以使用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,你的代码将会崩溃。

当然可以 - 但我期望一个覆盖了 Ctx 但没有覆盖 foo 的实例会拒绝编译。不过,这看起来是一个很好的解决方案! - Impredicative

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接