如何从 Haskell 中的不同类型级别强制转换类型?
How to coerce types from different type levels in Haskell?
我有以下代码:
type Name = String
data Level = T0 | T1 | T2
data T (l :: Level) where
Tint :: T t
Tdyn :: T t
Tbool :: T t
Tarr :: T 'T0 -> T 'T0 -> T t
Tand :: T 'T1 -> T 'T1 -> T 'T1
Tarr2 :: T 'T1 -> T 'T2 -> T 'T2
class Arr (l1 :: Level) (l2 :: Level) (l3 :: Level) | l3 -> l1 l2 where
infixr 3 ~>
(~>) :: T l1 -> T l2 -> T l3
instance Arr 'T0 'T0 'T0 where
(~>) = Tarr
instance Arr 'T0 'T0 'T1 where
(~>) = Tarr
instance Arr 'T1 'T2 'T2 where
(~>) = Tarr2
infixr 5 /\
(/\) :: T 'T1 -> T 'T1 -> T 'T1
(/\) = Tand
infixr 3 ~.>
(~.>) :: T 'T0 -> T 'T0 -> T t
(~.>) = Tarr
infixr 3 ~!>
(~!>) :: T 'T1 -> T 'T2 -> T 'T2
(~!>) = Tarr2
type Typ2 = T 'T2
type Typ1 = T 'T1
type Typ0 = T 'T0
int :: T t
int = Tint
bool :: T t
bool = Tbool
dyn :: T t
dyn = Tdyn
newType :: Typ2
newType = int /\ int ~> int /\ int ~> dyn
data Expr = Vi Int
| Vb Bool
| Vv Name
| App Expr Expr
| Lam Name Typ1 Expr
deriving(Generic)
type Env = [(Name,Typ1)]
基本上,我有三种类型。 T0、T1 和 T2。请注意,T0 也是 T1,T0 也是 T2。
我想用下面的签名写一个类型检查器:
typecheck :: Expr -> Env -> [Typ2]
它需要用这个签名调用一个函数:
Name -> Env -> [Typ0]
问题是我无法根据编译器将 [Typ0] 作为 [Typ2] 返回,所以我假设我需要进行强制转换?
有人知道在这种情况下最好做什么吗?
编辑:
typecheck :: Expr -> Env -> [Typ2]
typecheck (Vv x) env = (envlookup x env)
envlookup :: Name -> Env -> [Typ0]
envlookup name =
\case
(n,t):xs
| n == name ->
case t of
int -> [int]
-- otherwise -> t
[] -> []
一个选择是编写一个提升类型级别的函数:
raise0 :: T T0 -> T t
raise0 Tint = Tint
raise0 Tdyn = Tdyn
raise0 Tbool = Tbool
raise0 (Tarr i e) = Tarr i e
特别是,这可以用于 Typ0 -> Typ2
类型。另一种方法是让您的环境类型将级别作为参数:
envlookup :: Name -> Env t -> [T t]
envlookup name env = [t | (n, t) <- env, n == name]
第三种选择是确保环境中的类型可以在任何级别使用:
newtype AnyT = AnyT (forall t. T t)
type Env = [(Name, AnyT)]
envlookup :: Name -> Env -> [T t]
envlookup name env = [t | (n, AnyT t) <- env, n == name]
我有以下代码:
type Name = String
data Level = T0 | T1 | T2
data T (l :: Level) where
Tint :: T t
Tdyn :: T t
Tbool :: T t
Tarr :: T 'T0 -> T 'T0 -> T t
Tand :: T 'T1 -> T 'T1 -> T 'T1
Tarr2 :: T 'T1 -> T 'T2 -> T 'T2
class Arr (l1 :: Level) (l2 :: Level) (l3 :: Level) | l3 -> l1 l2 where
infixr 3 ~>
(~>) :: T l1 -> T l2 -> T l3
instance Arr 'T0 'T0 'T0 where
(~>) = Tarr
instance Arr 'T0 'T0 'T1 where
(~>) = Tarr
instance Arr 'T1 'T2 'T2 where
(~>) = Tarr2
infixr 5 /\
(/\) :: T 'T1 -> T 'T1 -> T 'T1
(/\) = Tand
infixr 3 ~.>
(~.>) :: T 'T0 -> T 'T0 -> T t
(~.>) = Tarr
infixr 3 ~!>
(~!>) :: T 'T1 -> T 'T2 -> T 'T2
(~!>) = Tarr2
type Typ2 = T 'T2
type Typ1 = T 'T1
type Typ0 = T 'T0
int :: T t
int = Tint
bool :: T t
bool = Tbool
dyn :: T t
dyn = Tdyn
newType :: Typ2
newType = int /\ int ~> int /\ int ~> dyn
data Expr = Vi Int
| Vb Bool
| Vv Name
| App Expr Expr
| Lam Name Typ1 Expr
deriving(Generic)
type Env = [(Name,Typ1)]
基本上,我有三种类型。 T0、T1 和 T2。请注意,T0 也是 T1,T0 也是 T2。
我想用下面的签名写一个类型检查器:
typecheck :: Expr -> Env -> [Typ2]
它需要用这个签名调用一个函数:
Name -> Env -> [Typ0]
问题是我无法根据编译器将 [Typ0] 作为 [Typ2] 返回,所以我假设我需要进行强制转换?
有人知道在这种情况下最好做什么吗?
编辑:
typecheck :: Expr -> Env -> [Typ2]
typecheck (Vv x) env = (envlookup x env)
envlookup :: Name -> Env -> [Typ0]
envlookup name =
\case
(n,t):xs
| n == name ->
case t of
int -> [int]
-- otherwise -> t
[] -> []
一个选择是编写一个提升类型级别的函数:
raise0 :: T T0 -> T t
raise0 Tint = Tint
raise0 Tdyn = Tdyn
raise0 Tbool = Tbool
raise0 (Tarr i e) = Tarr i e
特别是,这可以用于 Typ0 -> Typ2
类型。另一种方法是让您的环境类型将级别作为参数:
envlookup :: Name -> Env t -> [T t]
envlookup name env = [t | (n, t) <- env, n == name]
第三种选择是确保环境中的类型可以在任何级别使用:
newtype AnyT = AnyT (forall t. T t)
type Env = [(Name, AnyT)]
envlookup :: Name -> Env -> [T t]
envlookup name env = [t | (n, AnyT t) <- env, n == name]