- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
注意这个程序:
class Convert a b where
convert :: a -> b
data A = A deriving Show
data B = B deriving Show
data C = C deriving Show
data D = DA A | DB B | DC C deriving Show
instance Convert A A where convert A = A
instance Convert A B where convert A = B
instance Convert A C where convert A = C
instance Convert B A where convert B = A
instance Convert B B where convert B = B
instance Convert B C where convert B = C
-- There is no way to convert from C to A
instance Convert C B where convert C = B
instance Convert C C where convert C = C
get (DA x) = convert x
get (DB x) = convert x
get (DC x) = convert x
main = do
print (get (DC C) :: B) -- Up to this line, code compiles fine.
print (get (DB B) :: A) -- Add this line and it doesn't, regardless of having a way to convert from B to A!
C
转换的实例至
B
来自
B
至
A
.然而,GHC 对前者进行类型检查,但对后者失败。经检查,似乎无法为
get
推断出足够通用的类型:
get :: (Convert A b, Convert B b, Convert C b) => D -> b
get
尝试做,而不改变其余的设置?
最佳答案
如果您的程序对您来说确实有效,那么您将能够编写 get
的类型这可以在 Haskell 中完成您想要的工作,而不是在 handwave 中。让我帮助你提高你的手波并揭示你在棍子上要求月亮的原因。
What I want to express is:
get :: (Convert a_contained_by_D b) => D -> b
, which seems impossible.
get :: (Convert A b, Convert B b, Convert C b) => D -> b
a
可以被
D
包含需要一次一个,才能转换为
b
.这就是您获得经典系统管理逻辑的原因:否
D
除非他们都能得到
b
.
D
中可能包含的类型。 ,而是包含在特定
D
中的类型您收到的输入。正确的?你要
print (get (DB B) :: A) -- this to work
print (get (DC C) :: A) -- this to fail
DB B
和
DC C
只是
D
的两个不同元素,并且就 Haskell 类型系统而言,在每个类型中
不同的东西都是一样的 .如果要区分
D
的元素, 那么你需要一个
D
- 悬垂类型。以下是我在 handwave 中的写法。
DInner :: D -> *
DInner (DA a) = A
DInner (DB b) = B
DInner (DC c) = C
get :: forall x. pi (d :: D) -> (Convert (DInner d) x) => x
get (DA x) = convert x
get (DB x) = convert x
get (DC x) = convert x
pi
是在运行时传递的数据的绑定(bind)形式(与
forall
不同),但取决于哪些类型(与
->
不同)。现在约束不是在谈论任意
D
s 但非常
d :: D
在你的手中,约束可以通过检查它的
DInner
来准确计算所需的内容。 .
pi
之外,你无话可说。 .
pi
正从天而降,还未落地。尽管如此,与月亮不同,它可以用一根棍子到达。毫无疑问,您会提示我正在更改设置,但实际上我只是将您的程序从大约 2017 年的 Haskell 翻译到 2015 年的 Haskell。您将
get
有一天,它用我挥手的那种类型回来了。
DataKinds
和
KindSignatures
并为您的类型构建单例(或让 Richard Eisenberg 为您完成)。
data A = A deriving Show
data Aey :: A -> * where -- think of "-ey" as an adjectival suffix
Aey :: Aey 'A -- as in "tomatoey"
data B = B deriving Show
data Bey :: B -> * where
Bey :: Bey 'B
data C = C deriving Show
data Cey :: C -> * where
Cey :: Cey 'C
data D = DA A | DB B | DC C deriving Show
data Dey :: D -> * where
DAey :: Aey a -> Dey (DA a)
DBey :: Bey b -> Dey (DB b)
DCey :: Cey c -> Dey (DC c)
DA a
存在于运行时提供
a
做,等等。
DInner
.开启
TypeFamilies
.
type family DInner (d :: D) :: * where
DInner (DA a) = A
DInner (DB b) = B
DInner (DC c) = C
RankNTypes
,现在你可以写
get :: forall x. forall d. Dey d -> (Convert (DInner d) x) => x
-- ^^^^^^^^^^^^^^^^^^
-- this is a plausible fake of pi (d :: D) ->
get
搞砸了。我们必须匹配类型级别
d
的运行时证据。是有代表性的。我们需要它来获得类型级别
d
专门计算
DInner
.如果我们有适当的
pi
,我们可以匹配
D
服务于双重职责的值,但现在,匹配
Dey d
反而。
get (DAey x) = convert x -- have x :: Aey a, need x :: A
get (DBey x) = convert x -- and so on
get (DCey x) = convert x -- and so forth
x
es 现在是单例,其中,到
convert
,我们需要基础数据。我们需要更多的单例设备。
singletons
库可以从中模板-Haskell 样板,但让我们看看发生了什么
class Sing (s :: k -> *) where -- s is the singleton family for some k
type Sung s :: * -- Sung s is the type-level version of k
sung :: s x -> Sung s -- sung is the demotion function
instance Sing Aey where
type Sung Aey = A
sung Aey = A
instance Sing Bey where
type Sung Bey = B
sung Bey = B
instance Sing Cey where
type Sung Cey = C
sung Cey = C
instance Sing Dey where
type Sung Dey = D
sung (DAey aey) = DA (sung aey)
sung (DBey bey) = DB (sung bey)
sung (DCey cey) = DC (sung cey)
get :: forall x. forall d. Dey d -> (Convert (DInner d) x) => x
get (DAey x) = convert (sung x)
get (DBey x) = convert (sung x)
get (DCey x) = convert (sung x)
pi
, 那些
DAey
s 将是实际的
DA
s 和那些
x
s 不再需要是
sung
.我的手电类型为
get
将是 Haskell,您的代码为
get
会没事的。但与此同时
main = do
print (get (DCey Cey) :: B)
print (get (DBey Bey) :: A)
DInner
和
get
的正确类型)似乎是有效的 Dependent Haskell,我们快到了。
关于haskell - 为什么类型系统拒绝我看似有效的程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28713994/
我遇到了一个奇怪的问题。我有这个: $(document).ready(function () {
我正在编写一个程序,它从列表中读取一些 ID,从中找出不同的 URL,然后将图像保存到我的 C: 驱动器中。 如果我在浏览器中导航到图像 URL,它们就会起作用。此外,如果我尝试从不同的服务器获取图像
我编写了一个 REST WCF RIA Silverlight 4.0 兼容服务,我可以从 javascript + jQuery.1.4.2.js + JSON2.js(当然,还可以从 .NET 4
我很确定这个网站实际上还没有得到回答。一劳永逸地,与 32 位有符号整数范围内的数字字符串匹配的最小正则表达式是什么,范围是 -2147483648至 2147483647 . 我必须使用正则表达式进
我有两个data.table;我想从那些与键匹配的元素中随机分配一个元素。我现在这样做的方式相当慢。 让我们具体点;这是一些示例数据: dt1<-data.table(id=sample(letter
我已经安装了 celery 、RabitMQ 和花。我可以浏览到花港。我有以下简单的工作人员,我可以将其附加到 celery 并从 python 程序调用: # -*- coding: utf-8 -
我正在使用 ScalaCheck 在 ScalaTest 中进行一些基于属性的测试。假设我想测试一个函数,f(x: Double): Double仅针对 x >= 0.0 定义的, 并返回 NaN对于
我想检查文件是否具有有效的 IMAGE_DOS_SIGNATURE (MZ) function isMZ(FileName : String) : boolean; var Signature: W
在 Herbert Schildt 的“Java:完整引用,第 9 版”中,有一个让我有点困惑的例子。它的关键点我无法理解可以概括为以下代码: class Test { public stat
我在工作中查看了一些代码,发现了一些我以前没有遇到过的东西: for (; ;) { // Some code here break; } 我们一直调用包含这个的函数,我最近才进去看看它是
在 Herbert Schildt 的“Java:完整引用,第 9 版”中,有一个让我有点困惑的例子。它的关键点我无法理解可以概括为以下代码: class Test { public stat
我试图编写一个函数,获取 2D 点矩阵和概率 p 并以概率 p 更改或交换每个点坐标 所以我问了一个question我试图使用二进制序列作为特定矩阵 swap_matrix=[[0,1],[1,0]]
这个问题在这里已经有了答案: Using / or \\ for folder paths in C# (5 个答案) 关闭 7 年前。 我在某个Class1中有这个功能: public v
PostgreSQL 10.4 我有一张 table : Column | Type ------------------------- id | integer| title
我正在 Postgresql 中编写一个函数,它将返回一些针对特定时区(输入)计算的指标。 示例结果: 主要问题是这只是一个指标。我需要从其他表中获取其他 9 个指标。 对于实现此目标的更简洁的方法有
我需要在 python 中模拟超几何分布(用于不替换采样元素的花哨词)。 设置:有一个装满人口许多弹珠的袋子。弹珠有两种类型,红色和绿色(在以下实现中,弹珠表示为 True 和 False)。从袋子中
我正在使用 MaterializeCSS 框架并动态填充文本输入。我遇到的一个问题是,在我关注该字段之前,valid 和 invalid css 类不会添加到我的字段中。 即使我调用 M.update
是否有重叠 2 个 div 的有效方法。 我有以下内容,但无法让它们重叠。 #top-border{width:100%; height:60px; background:url(image.jpg)
我希望你们中的一位能向我解释为什么编译器要求我在编译单元中重新定义一个静态固定长度数组,尽管我已经在头文件中这样做了。这是一个例子: 我的类.h: #ifndef MYCLASS_H #define
我正在使用旧线程发布试图解决相同问题的新代码。什么是安全 pickle ? this? socks .py from socket import socket from socket import A
我是一名优秀的程序员,十分优秀!