我们可以获得[Int]
使用Dict
{-# LANGUAGE ConstraintKinds, GADTs #-}
data Dict (p :: Constraint) where
Dict :: p => Dict p
和
proof = Dict :: Dict (Show [Int])
有没有办法获得价值水平推导,即整个证明树?
derivation = Apply@Int(Lam a.(Show a) :=> Show [a])) (Apply(() :=> Show Int)())
答案 0 :(得分:4)
没有办法将任意约束推导为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])
答案 1 :(得分:1)
这可能是您所追求的,或者至少足以让您了解一般情况。我无法想办法让GHC自动提供,但您可以手动构建使用constraints
包证明约束的蕴涵链。
无论出于何种原因,都没有instance () :=> Show Int
,因此我使用了Char
。这可能是一种疏忽,我已经打开了一个拉取请求来添加丢失的实例。
{-# LANGUAGE ConstraintKinds #-}
import Data.Constraints
derivation :: () :- Show [Char]
derivation = trans showList showChar
where showList :: Show a :- Show [a]
showList = ins
showChar :: () :- Show Char
showChar = ins
不幸的是,打印此值并不会显示内部派生,而只是"Sub Dict"
。
有趣的练习可能是尝试使用derivation
使用明确TypeApplications
来撰写Data.Constraint.Forall
。您需要采取一些额外步骤来证明Show a :- Forall Show
和ForallF Show [] :- Show [a]
。