- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试进行一些高级类型级编程;该示例是我的原始程序的简化版本。
我有(Haskell)类型的表示。在这个例子中我只介绍函数类型、基本类型和类型变量。
表示Type t
由一个类型变量 t
参数化还允许在类型级别上进行区分。为了实现这一点,我主要使用 GADT。不同的类型和类型变量通过使用类型级别文字来区分,因此 KnownSymbol
约束和使用Proxy
s。
{-# LANGUAGE GADTs, TypeOperators, DataKinds, KindSignatures, TypeFamilies, PolyKinds #-}
import GHC.TypeLits
import Data.Proxy
import Data.Type.Equality
data Type :: TypeKind -> * where
TypeFun :: Type a -> Type b -> Type (a :-> b)
Type :: KnownSymbol t => Proxy t -> Type (Ty t)
TypeVar :: KnownSymbol t => Proxy t -> Type (TyVar t)
我还限制了 t
的类型友善TypeKind
通过使用 DataKinds 和 KindSignatures 扩展并定义 TypeKind
数据类型:
data TypeKind =
Ty Symbol
| TyVar Symbol
| (:->) TypeKind TypeKind
现在我想实现类型变量的替换,即在类型 t
内进行替换,每个变量x
等于类型变量 y
,类型为t'
。替换必须在表示以及类型级别上实现。对于后者,我们需要 TypeFamilies:
type family Subst (t :: TypeKind) (y :: Symbol) (t' :: TypeKind) :: TypeKind where
Subst (Ty t) y t' = Ty t
Subst (a :-> b) y t' = Subst a y t' :-> Subst b y t'
Subst (TyVar x) y t' = IfThenElse (x == y) t' (TyVar x)
类型变量是有趣的部分,因为我们检查符号 x
的相等性和y
在类型级别上。为此,我们还需要一个(多类)类型族,它允许我们在两个结果之间进行选择:
type family IfThenElse (b :: Bool) (x :: k) (y :: k) :: k where
IfThenElse True x y = x
IfThenElse False x y = y
不幸的是,这还没有编译,这可能是我的问题的第一个指标:
Nested type family application
in the type family application: IfThenElse (x == y) t' ('TyVar x)
(Use UndecidableInstances to permit this)
In the equations for closed type family ‘Subst’
In the type family declaration for ‘Subst’
不过,启用 UndecidableInstances 扩展是有效的,因此我们继续定义一个函数 subst
适用于值(value)级别:
subst :: (KnownSymbol y) => Type t -> Proxy (y :: Symbol) -> Type t' -> Type (Subst t y t')
subst (TypeFun a b) y t = TypeFun (subst a y t) (subst b y t)
subst t@(Type _) _ _ = t
subst t@(TypeVar x) y t'
| Just Refl <- sameSymbol x y = t'
| otherwise = t
这段代码工作完美,除了最后一行产生以下编译错误:
Could not deduce (IfThenElse
(GHC.TypeLits.EqSymbol t1 y) t' ('TyVar t1)
~ 'TyVar t1)
from the context (t ~ 'TyVar t1, KnownSymbol t1)
bound by a pattern with constructor
TypeVar :: forall (t :: Symbol).
KnownSymbol t =>
Proxy t -> Type ('TyVar t),
in an equation for ‘subst’
at Type.hs:29:10-18
Expected type: Type (Subst t y t')
Actual type: Type t
Relevant bindings include
t' :: Type t' (bound at Type.hs:29:23)
y :: Proxy y (bound at Type.hs:29:21)
x :: Proxy t1 (bound at Type.hs:29:18)
subst :: Type t -> Proxy y -> Type t' -> Type (Subst t y t')
(bound at Type.hs:27:1)
In the expression: t
In an equation for ‘subst’:
subst t@(TypeVar x) y t'
| Just Refl <- sameSymbol x y = t'
| otherwise = t
我猜问题是我无法证明两个符号的类型不相等x
和y
,并且需要某种类型不等式见证。这可能吗?或者还有其他更好的方法来实现我的目标吗?不知道问题到什么程度'idiomatic' Haskell type inequality和 Can GADTs be used to prove type inequalities in GHC?已经回答我的问题了。任何帮助将不胜感激。
最佳答案
正如 chi 在评论中所说,您需要的是 Either ((x==y) :~: True) ((x==y) :~: False)
。不幸的是,类型文字目前有部分被破坏,这是我们只能使用 unsafeCoerce
做的事情之一(尽管在道德上是可以接受的用途)。
sameSymbol' ::
(KnownSymbol s, KnownSymbol s') =>
Proxy s -> Proxy s'
-> Either ((s == s') :~: True) ((s == s') :~: False)
sameSymbol' s s' = case sameSymbol s s' of
Just Refl -> Left Refl
Nothing -> Right (unsafeCoerce Refl)
subst :: (KnownSymbol y) => Type t -> Proxy (y :: Symbol) -> Type t' -> Type (Subst t y t')
subst (TypeFun a b) y t = TypeFun (subst a y t) (subst b y t)
subst t@(Type _) _ _ = t
subst t@(TypeVar x) y t' = case sameSymbol' x y of
Left Refl -> t'
Right Refl -> t
另一方面,如果您不介意一些 Haskell 模板,则 singletons
库可以导出您的定义(以及更多):
{-# language GADTs, TypeOperators, DataKinds, KindSignatures, TypeFamilies, PolyKinds #-}
{-# language UndecidableInstances, ScopedTypeVariables, TemplateHaskell, FlexibleContexts #-}
import GHC.TypeLits
import Data.Singletons.TH
import Data.Singletons.Prelude
singletons([d|
data Type sym
= Ty sym
| TyVar sym
| Type sym :-> Type sym
subst :: Eq sym => Type sym -> sym -> Type sym -> Type sym
subst (Ty t) y t' = Ty t
subst (a :-> b) y t' = subst a y t' :-> subst b y t'
subst (TyVar x) y t' = if x == y then t' else TyVar x
|])
这为我们提供了 Type
和 subst
的类型、种类和值级别定义。示例:
-- some examples
-- type level
type T1 = Ty "a" :-> TyVar "b"
type T2 = Subst T1 "b" (Ty "c") -- this equals (Ty "a" :-> Ty "c")
-- value level
-- automatically create value-level representation of T1
t1 = sing :: Sing T1
-- or write it out by hand
t1' = STy (sing :: Sing "a") :%-> STyVar (sing :: Sing "b")
-- use value-level subst on t1:
t2 = sSubst t1 (sing :: Sing "b") (STy (sing :: Sing "c"))
-- or generate result from type-level representation
t2' = sing :: Sing (Subst T1 "b" (Ty "c"))
-- Convert singleton to non-singleton (and print it)
t3 :: Type String
t3 = fromSing t2 -- Ty "a" :-> Ty "c"
关于haskell - 在 Haskell 的类型级编程中使用类型不等式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37388587/
我正在尝试打印 timeval 类型的值。实际上我可以打印它,但我收到以下警告: 该行有多个标记 格式“%ld”需要“long int”类型,但参数 2 的类型为“struct timeval” 程序
我正在编写自己的 unix 终端,但在执行命令时遇到问题: 首先,我获取用户输入并将其存储到缓冲区中,然后我将单词分开并将它们存储到我的 argv[] 数组中。IE命令是“firefox”以启动存储在
我是 CUDA 的新手。我有一个关于一个简单程序的问题,希望有人能注意到我的错误。 __global__ void ADD(float* A, float* B, float* C) { con
我有一个关于 C 语言 CGI 编程的一般性问题。 我使用嵌入式 Web 服务器来处理 Web 界面。为此,我在服务器中存储了一个 HTML 文件。在此 HTML 文件中包含 JavaScript 和
**摘要:**在代码的世界中,是存在很多艺术般的写法,这可能也是部分程序员追求编程这项事业的内在动力。 本文分享自华为云社区《【云驻共创】用4种代码中的艺术试图唤回你对编程的兴趣》,作者: break
我有一个函数,它的任务是在父对象中创建一个变量。我想要的是让函数在调用它的级别创建变量。 createVariable testFunc() [1] "test" > testFunc2() [1]
以下代码用于将多个连续的空格替换为1个空格。虽然我设法做到了,但我对花括号的使用感到困惑。 这个实际上运行良好: #include #include int main() { int ch, la
我正在尝试将文件写入磁盘,然后自动重新编译。不幸的是,某事似乎不起作用,我收到一条我还不明白的错误消息(我是 C 初学者 :-)。如果我手动编译生成的 hello.c,一切正常吗?! #include
如何将指针值传递给结构数组; 例如,在 txt 上我有这个: John Doe;xxxx@hotmail.com;214425532; 我的代码: typedef struct Person{
我尝试编写一些代码来检索 objectID,结果是 2B-06-01-04-01-82-31-01-03-01-01 . 这个值不正确吗? // Send a SysObjectId SNMP req
您好,提前感谢您的帮助, (请注意评论部分以获得更多见解:即,以下示例中的成本列已添加到此问题中;西蒙提供了一个很好的答案,但成本列本身并未出现在他的数据响应中,尽管他提供的功能与成本列一起使用) 我
我想知道是否有人能够提出一些解决非线性优化问题的软件包的方法,而非线性优化问题可以为优化解决方案提供整数变量?问题是使具有相等约束的函数最小化,该函数受某些上下边界约束的约束。 我已经在R中使用了'n
我是 R 编程的初学者,正在尝试向具有 50 列的矩阵添加一个额外的列。这个新列将是该行中前 10 个值的平均值。 randomMatrix <- generateMatrix(1,5000,100,
我在《K&R II C 编程 ANSI C》一书中读到,“>>”和“0; nwords--) sum += *buf++; sum = (sum >>
当下拉列表的选择发生变化时,我想: 1) 通过 div 在整个网站上显示一些 GUI 阻止覆盖 2)然后处理一些代码 3) 然后隐藏叠加层。 问题是,当我在事件监听器函数中编写此逻辑时,将执行 onC
我正在使用 Clojure 和 RESTEasy 设计 JAX-RS REST 服务器. 据我了解,用 Lisp 系列语言编写的应用程序比用“传统”命令式语言编写的应用程序更多地构建为“特定于领域的语
我目前正在研究一种替代出勤监控系统作为一项举措。目前,我设计的用户表单如下所示: Time Stamp Userform 它的工作原理如下: 员工将选择他/她将使用的时间戳类型:开始时间、超时、第一次
我是一名学生,试图自学编程,从在线资源和像您这样的人那里获得帮助。我在网上找到了一个练习来创建一个小程序来执行此操作: 编写一个程序,读取数字 a 和 b(长整型)并列出 a 和 b 之间有多少个数字
我正在尝试编写一个 shell 程序,给定一个参数,打印程序的名称和参数中的每个奇数词(即,不是偶数词)。但是,我没有得到预期的结果。在跟踪我的程序时,我注意到,尽管奇数词(例如,第 5 个词,5 %
只是想知道是否有任何 Java API 可以让您控制台式机/笔记本电脑外壳上的 LED? 或者,如果不可能,是否有可能? 最佳答案 如果你说的是前面的 LED 指示电源状态和 HDD 繁忙状态,恐怕没
我是一名优秀的程序员,十分优秀!