Haskell 在运行时使用GADTs进行类型转换
我正在设计一种类型化的正式语言,也就是说,一种正式语言,其中每个字母都有特定类型的表示。到目前为止,我有以下几点:Haskell 在运行时使用GADTs进行类型转换,haskell,gadt,existential-type,Haskell,Gadt,Existential Type,我正在设计一种类型化的正式语言,也就是说,一种正式语言,其中每个字母都有特定类型的表示。到目前为止,我有以下几点: {-#语言数据类型} {-#语言灵活语境#-} {-#语言灵活实例} {-#语言GADTs} {-#语言实例sigs} {-#语言等级} {-#语言范围类型变量#-} {-#语言类型#-} {-#语言类型族{-} 导入数据。种类 数据类型Y(s::c)=标记 类字符c,其中 showVal::Typey(s::ca)->a->ShowS 类别字符(字母l)=>字母l,其中 数据族字
{-#语言数据类型}
{-#语言灵活语境#-}
{-#语言灵活实例}
{-#语言GADTs}
{-#语言实例sigs}
{-#语言等级}
{-#语言范围类型变量#-}
{-#语言类型#-}
{-#语言类型族{-}
导入数据。种类
数据类型Y(s::c)=标记
类字符c,其中
showVal::Typey(s::ca)->a->ShowS
类别字符(字母l)=>字母l,其中
数据族字母l::*->*
数据符号l(a::字母l s),其中
终端::(字母l)=>s->符号l(a::字母l-s)
实例(字母l)=>显示(符号LA)其中
showsPrec d(终端val)=showVal(标记::类型Y a)val
--示例语言
数据示例语言=示例语言
实例字母表示例语言在哪里
数据字母示例语言a where
变量::字母ExampleLanguage字符串
Comment::Letter example语言字符串
EqualSign::Letter ExampleLanguage()
Deref::Letter ExampleLanguage()
实例字符(字母ExampleLanguage),其中
--showVal(\:Typey变量)=showString
--showVal(\:Typey Comment)=showString
--showVal(\:Typey EqualSign)=常量$showString“=”
--showVal(\:Typey Deref)=const$showString“*”
showVal=常量$showString“错误”
测试::符号示例语言注释
测试=终端“一些注释”
您可能已经看到我开始实现showVal
,但是在这里,我在完成实现时遇到了问题。当我尝试取消注释实例字母(Character ExampleLanguage)
中的行时,编译器很快就会抱怨:
main.hs:40:14: error:
• Couldn't match type ‘a1’ with ‘()’
‘a1’ is a rigid type variable bound by
the type signature for:
showVal :: forall k (a :: k) a1 (s :: Character
ExampleLanguage a1).
Typey s -> a1 -> ShowS
at main.hs:38:5
Expected type: Typey 'EqualSign
Actual type: Typey s
• When checking that the pattern signature: Typey 'EqualSign
fits the type of its context: Typey s
In the pattern: _ :: Typey EqualSign
In an equation for ‘showVal’:
showVal (_ :: Typey EqualSign) = const $ showString "="
• Relevant bindings include
showVal :: Typey s -> a1 -> ShowS (bound at main.hs:38:5)
我不确定我是否理解编译器在抱怨什么。从Character ExampleLanguage
的GADT定义可以清楚地看出,我正在尝试模式匹配不同的构造函数,根据字母输出不同的字符串
我怎样才能做到这一点?数据格式不是固定的,只要
符号
包含有关字母表、字母和字母表示类型的类型信息,就可以随意修改它。模式匹配GADT的构造函数,而不是它们的类型
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
class Character c where
showVal :: c a -> a -> ShowS
class Character (Letter l) => Alphabet l where
data family Letter l :: * -> *
-- Example language
data ExampleLanguage = ExampleLanguage
instance Alphabet ExampleLanguage where
data Letter ExampleLanguage a where
Variable :: Letter ExampleLanguage String
Comment :: Letter ExampleLanguage String
EqualSign :: Letter ExampleLanguage ()
Deref :: Letter ExampleLanguage ()
instance Character (Letter ExampleLanguage) where
showVal Variable = showString
showVal Comment = showString
showVal EqualSign = const $ showString "="
showVal Deref = const $ showString "*"
将此标记包含在符号中
,以便以后可以在其上进行模式匹配
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeInType #-}
data Symbol l (a :: Letter l s) where
Terminal :: Letter l s -> s -> Symbol l (a :: Letter l s)
instance (Alphabet l) => Show (Symbol l a) where
showsPrec d (Terminal tag val) = showVal tag val
test :: Symbol ExampleLanguage Comment
test = Terminal Comment "some comment"
模式匹配在GADT的构造函数上,而不是在其类型上
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
class Character c where
showVal :: c a -> a -> ShowS
class Character (Letter l) => Alphabet l where
data family Letter l :: * -> *
-- Example language
data ExampleLanguage = ExampleLanguage
instance Alphabet ExampleLanguage where
data Letter ExampleLanguage a where
Variable :: Letter ExampleLanguage String
Comment :: Letter ExampleLanguage String
EqualSign :: Letter ExampleLanguage ()
Deref :: Letter ExampleLanguage ()
instance Character (Letter ExampleLanguage) where
showVal Variable = showString
showVal Comment = showString
showVal EqualSign = const $ showString "="
showVal Deref = const $ showString "*"
将此标记包含在符号中
,以便以后可以在其上进行模式匹配
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeInType #-}
data Symbol l (a :: Letter l s) where
Terminal :: Letter l s -> s -> Symbol l (a :: Letter l s)
instance (Alphabet l) => Show (Symbol l a) where
showsPrec d (Terminal tag val) = showVal tag val
test :: Symbol ExampleLanguage Comment
test = Terminal Comment "some comment"
我不知道如何用这种方法实现
实例(字母l)=>显示(符号l a)
a
是这种情况下的特定字母,但它在类型信息中,不能作为参数传递给showVal,对吗?除非GHC中有一些我不知道的进展,类型Symbol example language Comment
没有意义,因为Comment
是GADT的构造函数,无法升级。GHC 8让我很惊讶。我添加了如何定义Symbol
。剩下的一个问题是:这现在是合法的:(终端注释“某些注释”)::Symbol ExampleLanguage变量
,即如果两个字母具有相同的类型,编译器将不会发现我在构造函数中输入了不同的字母和类型,我不知道如何实现实例(字母l)=>显示(符号l a)在这种情况下,a
是特定的字母,但它在类型信息中,不能作为参数传递到showVal中,对吗?除非GHC中有一些我不知道的进展,否则类型符号ExampleLanguage Comment
没有意义,因为Comment
是G的构造函数ADT和无法升级。GHC 8让我很惊讶。我添加了如何定义符号
。还有一个问题:这现在是合法的:(终端注释“某些注释”)::Symbol example language Variable
即如果两个字母具有相同的类型,编译器将不会发现我在构造函数和类型中输入了不同的字母