没有办法将任意约束派生为Haskell值。
我能想到的最接近的事情是,如果你想检查派生是否是你认为的那样,就是看清楚输出。
ghc -ddump-ds -ddump-to-file A.hs
相关部分看起来是这样的:
-- RHS size: {terms: 2, types: 1, coercions: 0, joins: 0/0}
irred :: Show [Int]
[LclId]
irred = GHC.Show.$fShow[] @ Int GHC.Show.$fShowInt
-- RHS size: {terms: 2, types: 3, coercions: 0, joins: 0/0}
proof :: Dict (Show [Int])
[LclIdX]
proof = Cns.Dict @ (Show [Int]) irred
另一个是编写自定义类型类仪表反映的推导,无论是在类型或价值观,当然,这并不适用于预先存在的类型类。
{-# LANGUAGE AllowAmbiguousTypes, ConstraintKinds, GADTs, DataKinds,
FlexibleInstances, KindSignatures, MultiParamTypeClasses, RankNTypes,
ScopedTypeVariables, TypeApplications, TypeOperators,
UndecidableInstances #-}
import Data.Typeable
import Data.Kind
data (c :: [Type]) :=> (d :: Type -> Constraint)
class MyShow a d where
myshow :: a -> String
instance (d ~ ('[] :=> MyShow Int)) => MyShow Int d where
instance (MyShow a da, d ~ ('[da] :=> MyShow [a])) => MyShow [a] d where
myshowInstance :: forall a d. (Typeable d, MyShow a d) => TypeRep
myshowInstance = typeRep @_ @d Proxy
main = print (myshowInstance @[Int])
输出可以作出更好看,例如,通过单用适当的渲染方法,而不是TypeRep
,但我希望你得到的主要思想。
:=> (': * (:=> ('[] *) (MyShow Int)) ('[] *)) (MyShow [Int])
这确实是一个有趣的练习! – nicolas