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,这将允许它编译。是否有任何原因这不起作用,或者任何人都可以提出一个好的方法来实现这一点?

4

1 回答 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

于 2014-07-28T14:45:30.157 回答