从类型类分辨率中获取派生

时间:2017-10-18 09:31:51

标签: haskell constraints typeclass

我们可以获得[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)()) 

2 个答案:

答案 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 ShowForallF Show [] :- Show [a]