Haskell 如何从具有类型相等约束的Scott编码GADT中获取值?
我正在阅读并遇到以下GADT:Haskell 如何从具有类型相等约束的Scott编码GADT中获取值?,haskell,gadt,continuation-passing,refinements,refinement-type,Haskell,Gadt,Continuation Passing,Refinements,Refinement Type,我正在阅读并遇到以下GADT: {-# LANGUAGE GADTs #-} {-# LANGUAGE KindSignatures #-} import Data.Char data Some :: * -> * where SomeInt :: Int -> Some Int SomeChar :: Char -> Some Char Anything :: a -> Some a unSome :: Some a -> a un
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
import Data.Char
data Some :: * -> * where
SomeInt :: Int -> Some Int
SomeChar :: Char -> Some Char
Anything :: a -> Some a
unSome :: Some a -> a
unSome (SomeInt x) = x + 3
unSome (SomeChar c) = toLower c
unSome (Anything x) = x
unSome (someInt 2) -- 5
尽管unSome
的类型变量是多态的,但可以向编译器证明,例如在SomeInt
的情况下,在给定的值上添加三个变量是安全的。作者称这种类型为细化
现在我很好奇,我是否可以用Scrott编码的类型做同样的事情。幸运的是,有这样一个编码的例子。我们只需要打开秩N类型和类型族扩展:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}
newtype SomeC a =
SomeC {
runSomeC ::
forall r.
((a ~ Int) => Int -> r) ->
((a ~ Char) => Char -> r) ->
(a -> r) ->
r
}
但是,本文没有提供unSome
。我不太熟悉Haskell,也不知道如何用Scott编码实现这个函数。尤其是类型相等约束(例如(a~Int)=>
)让我感到困惑
非常感谢您提供有关其他在线资源的任何帮助或信息。您只需使用提供的功能替换模式匹配,如:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}
import Data.Char
newtype SomeC a =
SomeC {
runSomeC ::
forall r.
((a ~ Int) => Int -> r) ->
((a ~ Char) => Char -> r) ->
(a -> r) ->
r
}
unSome :: SomeC a -> a
unSome (SomeC f) = f (\x -> x+3) (\c -> toLower c) (\x -> x)
在ghci中:
> unSome (SomeC (\someInt someChar anything -> someInt 2))
5
与处理任何其他CPS编码的数据类型(“Scrott”)的方法完全相同—将对应于每种情况的函数作为输入传递给消除函数。您可以编写一个等价的
unSome
作为\k->runSomeC k(+3)toUpper id
@user2407038,但是(a~Int)=>
引入的魔力在哪里呢?很抱歉,我真的不明白这个约束实际上在做什么。@t或者请注意,SomeC a
的用户可以选择r
作为提及a
的类型;e、 g.在编写unSome
时,他们会选择r~a
。然后再加上a~Int
,这意味着他们可以从Int->r
部分获得Int
。就这么简单!显然,类型的定义比它的实现更困难。因此(a~Char)=>
不是一个隐式函数。那是什么?仅仅是一个相等的断言?((a~Char)=>a->r)->r
意味着“给定一个函数,该函数可以假定a
是Char
,并将a
作为输入,作为输出r
,作为输出r
”。它只是一个约束-与例如(Show a=>a->r)->r
@ftor是的,它是一个平等的断言。断言在编译时被检查,并且可以在编译时用于将显然属于提及等式一侧的类型的项转换为提及等式另一侧的类型的项。取决于您希望从“指称语义”到“这些语义的实现如何工作”。。。在GHC中,它也是一个隐式函数,它将一种类型等于另一种类型的证据作为参数,以编译器在将术语从一种类型转换为另一种类型时可以发出的强制形式。这意味着我不能断言a
是一个奇数整数,因为编译器无法在编译时确定这一点?