Haskell 从类型类解析中获取派生
我们可以使用Haskell 从类型类解析中获取派生,haskell,constraints,typeclass,Haskell,Constraints,Typeclass,我们可以使用Dict得到[Int]有一个Show实例的值级证明 {-# LANGUAGE ConstraintKinds, GADTs #-} data Dict (p :: Constraint) where Dict :: p => Dict p 及 有没有一种方法可以得到一个值级的派生,即整个证明树 derivation = Apply@Int(Lam a.(Show a) :=> Show [a])) (Apply(() :=> Show Int)()) 没有
Dict
得到[Int]
有一个Show实例的值级证明
{-# LANGUAGE ConstraintKinds, GADTs #-}
data Dict (p :: Constraint) where
Dict :: p => Dict p
及
有没有一种方法可以得到一个值级的派生,即整个证明树
derivation = Apply@Int(Lam a.(Show a) :=> Show [a])) (Apply(() :=> Show Int)())
没有一种方法可以将任意约束的派生作为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])
这可能是你想要的,或者至少足以给你一个大致的想法。我想不出一种让GHC自动提供的方法,但是您可以使用
constraints
包手动构建证明约束的包含链
无论出于何种原因,都没有实例():=>Show Int
,因此我使用了Char
。这可能是一个疏忽,我打开了一个pull请求来添加缺少的实例
{-# 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”
一个有趣的练习可能是尝试使用
Data.Constraint.Forall
使用显式TypeApplications
编写派生
。你还需要几个额外的步骤来证明Show a:-Forall Show
和ForallF Show[]:-Show[a]
这确实是一个有趣的练习!
{-# 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