- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我尝试实现一个完美平衡的二叉搜索树,其中大小作为类型参数给出(就像 C++ 的 std::array
所做的那样)。
这是树的实现:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
import GHC.TypeNats
import Data.Foldable hiding (length)
import Data.Monoid
import Data.Proxy
data MultiSet (n :: Nat) a where
Leaf :: MultiSet 0 a
Odd :: MultiSet n a -> a -> MultiSet n a -> MultiSet (n+n+1) a
Even :: MultiSet n a -> a -> a -> MultiSet n a -> MultiSet (n+n+2) a
这是 minView
的实现,与 containers
包中的 Data.Set
类似:
minView :: MultiSet (n+1) a -> (a, MultiSet n a)
minView (Odd Leaf x Leaf) = (x, Leaf)
minView (Even Leaf x y Leaf) = (x, Odd Leaf y Leaf)
minView (Odd l x r) = let
(u, l') = minView l
(v, r') = minView r
in (u, Even l' x v r')
minView (Even l x y r) = let
(u, l') = minView l
in (u, Odd (insert x l') y r)
但是当我尝试解释它时会出现许多错误:
PerfectBalance.hs:71:33: error:
• Could not deduce: n ~ 0
from the context: (n + 1) ~ ((n5 + n5) + 1)
bound by a pattern with constructor:
Odd :: forall (n :: Nat) a.
MultiSet n a -> a -> MultiSet n a -> MultiSet ((n + n) + 1) a,
in an equation for ‘minView’
at PerfectBalance.hs:71:10-24
or from: n5 ~ 0
bound by a pattern with constructor:
Leaf :: forall a. MultiSet 0 a,
in an equation for ‘minView’
at PerfectBalance.hs:71:14-17
‘n’ is a rigid type variable bound by
the type signature for:
minView :: forall (n :: Nat) a.
MultiSet (n + 1) a -> (a, MultiSet n a)
at PerfectBalance.hs:70:1-48
Expected type: MultiSet n a
Actual type: MultiSet 0 a
• In the expression: Leaf
In the expression: (x, Leaf)
In an equation for ‘minView’: minView (Odd Leaf x Leaf) = (x, Leaf)
• Relevant bindings include
minView :: MultiSet (n + 1) a -> (a, MultiSet n a)
(bound at PerfectBalance.hs:71:1)
|
71 | minView (Odd Leaf x Leaf) = (x, Leaf)
| ^^^^
PerfectBalance.hs:72:36: error:
• Could not deduce: n ~ 1
from the context: (n + 1) ~ ((n5 + n5) + 2)
bound by a pattern with constructor:
Even :: forall (n :: Nat) a.
MultiSet n a -> a -> a -> MultiSet n a -> MultiSet ((n + n) + 2) a,
in an equation for ‘minView’
at PerfectBalance.hs:72:10-27
or from: n5 ~ 0
bound by a pattern with constructor:
Leaf :: forall a. MultiSet 0 a,
in an equation for ‘minView’
at PerfectBalance.hs:72:15-18
‘n’ is a rigid type variable bound by
the type signature for:
minView :: forall (n :: Nat) a.
MultiSet (n + 1) a -> (a, MultiSet n a)
at PerfectBalance.hs:70:1-48
Expected type: MultiSet n a
Actual type: MultiSet ((0 + 0) + 1) a
• In the expression: Odd Leaf y Leaf
In the expression: (x, Odd Leaf y Leaf)
In an equation for ‘minView’:
minView (Even Leaf x y Leaf) = (x, Odd Leaf y Leaf)
• Relevant bindings include
minView :: MultiSet (n + 1) a -> (a, MultiSet n a)
(bound at PerfectBalance.hs:71:1)
|
72 | minView (Even Leaf x y Leaf) = (x, Odd Leaf y Leaf)
| ^^^^^^^^^^^^^^^
PerfectBalance.hs:75:23: error:
• Could not deduce: (n2 + 1) ~ n5
from the context: (n + 1) ~ ((n5 + n5) + 1)
bound by a pattern with constructor:
Odd :: forall (n :: Nat) a.
MultiSet n a -> a -> MultiSet n a -> MultiSet ((n + n) + 1) a,
in an equation for ‘minView’
at PerfectBalance.hs:73:10-18
‘n5’ is a rigid type variable bound by
a pattern with constructor:
Odd :: forall (n :: Nat) a.
MultiSet n a -> a -> MultiSet n a -> MultiSet ((n + n) + 1) a,
in an equation for ‘minView’
at PerfectBalance.hs:73:10-18
Expected type: MultiSet (n2 + 1) a
Actual type: MultiSet n5 a
• In the first argument of ‘minView’, namely ‘r’
In the expression: minView r
In a pattern binding: (v, r') = minView r
• Relevant bindings include
r' :: MultiSet n2 a (bound at PerfectBalance.hs:75:9)
r :: MultiSet n5 a (bound at PerfectBalance.hs:73:18)
l :: MultiSet n5 a (bound at PerfectBalance.hs:73:14)
|
75 | (v, r') = minView r
| ^
PerfectBalance.hs:76:12: error:
• Could not deduce: ((n2 + n2) + 2) ~ n
from the context: (n + 1) ~ ((n5 + n5) + 1)
bound by a pattern with constructor:
Odd :: forall (n :: Nat) a.
MultiSet n a -> a -> MultiSet n a -> MultiSet ((n + n) + 1) a,
in an equation for ‘minView’
at PerfectBalance.hs:73:10-18
‘n’ is a rigid type variable bound by
the type signature for:
minView :: forall (n :: Nat) a.
MultiSet (n + 1) a -> (a, MultiSet n a)
at PerfectBalance.hs:70:1-48
Expected type: MultiSet n a
Actual type: MultiSet ((n2 + n2) + 2) a
• In the expression: Even l' x v r'
In the expression: (u, Even l' x v r')
In the expression:
let
(u, l') = minView l
(v, r') = minView r
in (u, Even l' x v r')
• Relevant bindings include
l' :: MultiSet n2 a (bound at PerfectBalance.hs:74:9)
r' :: MultiSet n2 a (bound at PerfectBalance.hs:75:9)
minView :: MultiSet (n + 1) a -> (a, MultiSet n a)
(bound at PerfectBalance.hs:71:1)
|
76 | in (u, Even l' x v r')
| ^^^^^^^^^^^^^^
PerfectBalance.hs:78:23: error:
• Could not deduce: (n3 + 1) ~ n5
from the context: (n + 1) ~ ((n5 + n5) + 2)
bound by a pattern with constructor:
Even :: forall (n :: Nat) a.
MultiSet n a -> a -> a -> MultiSet n a -> MultiSet ((n + n) + 2) a,
in an equation for ‘minView’
at PerfectBalance.hs:77:10-21
‘n5’ is a rigid type variable bound by
a pattern with constructor:
Even :: forall (n :: Nat) a.
MultiSet n a -> a -> a -> MultiSet n a -> MultiSet ((n + n) + 2) a,
in an equation for ‘minView’
at PerfectBalance.hs:77:10-21
Expected type: MultiSet (n3 + 1) a
Actual type: MultiSet n5 a
• In the first argument of ‘minView’, namely ‘l’
In the expression: minView l
In a pattern binding: (u, l') = minView l
• Relevant bindings include
l' :: MultiSet n3 a (bound at PerfectBalance.hs:78:9)
r :: MultiSet n5 a (bound at PerfectBalance.hs:77:21)
l :: MultiSet n5 a (bound at PerfectBalance.hs:77:15)
|
78 | (u, l') = minView l
| ^
PerfectBalance.hs:79:12: error:
• Could not deduce: ((n5 + n5) + 1) ~ n
from the context: (n + 1) ~ ((n5 + n5) + 2)
bound by a pattern with constructor:
Even :: forall (n :: Nat) a.
MultiSet n a -> a -> a -> MultiSet n a -> MultiSet ((n + n) + 2) a,
in an equation for ‘minView’
at PerfectBalance.hs:77:10-21
‘n’ is a rigid type variable bound by
the type signature for:
minView :: forall (n :: Nat) a.
MultiSet (n + 1) a -> (a, MultiSet n a)
at PerfectBalance.hs:70:1-48
Expected type: MultiSet n a
Actual type: MultiSet ((n5 + n5) + 1) a
• In the expression: Odd (insert x l') y r
In the expression: (u, Odd (insert x l') y r)
In the expression:
let (u, l') = minView l in (u, Odd (insert x l') y r)
• Relevant bindings include
r :: MultiSet n5 a (bound at PerfectBalance.hs:77:21)
l :: MultiSet n5 a (bound at PerfectBalance.hs:77:15)
minView :: MultiSet (n + 1) a -> (a, MultiSet n a)
(bound at PerfectBalance.hs:71:1)
|
79 | in (u, Odd (insert x l') y r)
| ^^^^^^^^^^^^^^^^^^^^^
maxView
、insert
和delete
也有类似的问题。
如何解决这些问题?
最佳答案
GHC 不懂代数。 任何代数。像n + 1 /= 0
之类的东西和n + 1 = m + 1 -> n = m
都超出了它。它最多能做的就是评估,例如 1 + 1 = 2
。你必须明确地将它们写成公理,并用 unsafeCoerce
来实现它们,并告诉 GHC 使用它们。 (或者,您可以使用编译器插件将 GHC 连接到求解器,可以进行代数运算并将这些结果转换为公理。)
此外,即使 GHC 可以做代数,在 Odd l x r
中和Even l x y r
案例,l, r :: MultiSet m a
m = m' + 1
不知道在哪里。也就是说,即使您已经匹配 l
和r
反对Leaf
,因此“证明” l
和r
含有不止一种元素,这一点未经 GHC 证明。粗略地说,“l
和r
非空”背后的推理不够“直接”。失败的匹配不会为您提供有关受审查者的更多类型信息。我会写一个辅助函数:
{-# LANGUAGE AllowAmbiguousTypes, ExplicitForAll, ScopedTypeVariables, TypeApplications #-}
import Data.Proxy
import Data.Type.Equality
import Data.Void
import Unsafe.Coerce
data NatCheck (n :: Nat) where
IsZero :: NatCheck 0
IsSucc :: Proxy n -> NatCheck (n + 1)
-- Proxy lets us bind the predecessor to a name
checkMultiSet :: forall n a. MultiSet n a -> NatCheck n
checkMultiSet Leaf = IsZero
checkMultiSet (Odd _ _ _) = IsSucc Proxy
-- get m :: Nat out of Even, learn n = (m + m) + (1 + 1) from it
-- reassociate: n = ((m + m) + 1) + 1
checkMultiSet (Even (_ :: MultiSet m a) _ _ _) | Refl <- addAssoc @(m + m) @1 @1 = IsSucc Proxy
-- axiom
addAssoc :: forall n m l. ((n + m) + l) :~: (n + (m + l))
addAssoc = unsafeCoerce Refl
并使用它而不是显式使用 MultiSet
的构造函数
{-# LANGUAGE EmptyCase #-}
minView :: forall n a. MultiSet (n + 1) a -> (a, MultiSet n a)
minView Leaf = case natDiscrim @n Refl of { } -- Leaf is not ruled out automatically, have to prove unreachability with axiom n + 1 /= 0
minView (Odd l x r) = -- get m :: Nat, learn n + 1 = m + m + 1, get l, r of size m
case checkMultiSet l of -- i.e. check m =? 0
-- learn m = 0, so n + 1 = 0 + 1
-- injectivity: n = 0
IsZero | Refl <- succInj @n @0 -> (x, Leaf)
-- get m' :: Nat, learn m = m' + 1
-- get l', r' of size m'
-- we know n + 1 = (m' + 1) + (m' + 1) + 1
-- the Even has size ((m' + m') + 2) when it should be n
-- algebra, except more painfully than ever before
-- injectivity gets: n = (m' + 1) + (m' + 1)
-- reassociate: n = ((m' + 1) + m') + 1
-- commute: n = (m' + (m' + 1)) + 1
-- reassociate: n = ((m' + m') + 1) + 1
-- reassociate: n = (m' + m') + (1 + 1)
IsSucc (Proxy :: Proxy m')
| (u, l') <- minView l, (v, r') <- minView r
, Refl <- succInj @n @((m' + 1) + (m' + 1))
, Refl <- addAssoc @(m' + 1) @m' @1
, Refl <- addComm @(m' + 1) @m'
, Refl <- addAssoc @m' @m' @1
, Refl <- addAssoc @(m' + m') @1 @1
-> (u, Even l' x v r')
minView (Even (l :: MultiSet m a) x y r) = -- get m :: Nat, learn n + 1 = m + m + 2, get l, r of size m
case checkMultiSet l of -- i.e. check m =? 0
-- learn m = 0, so n + 1 = 1 + 1
-- injectivity: n = 1
IsZero | Refl <- succInj @n @1 -> (x, Odd Leaf y Leaf)
-- get m' :: Nat, learn m = m' + 1, get l' of size m'
-- we know n + 1 = (m + m) + (1 + 1)
-- the Odd has size ((m + m) + 1) when it should be n
-- algebra, less painful
-- reassociate: n + 1 = ((m + m) + 1) + 1
-- injectivity: n = (m + m) + 1
IsSucc _
| (u, l') <- minView l
, Refl <- addAssoc @(m + m) @1 @1
, Refl <- succInj @n @(m + m + 1)
-> (u, Odd (insert x l') y r)
-- more axioms
natDiscrim :: forall n. (n + 1) :~: 0 -> Void
natDiscrim Refl = error "natDiscrim: impossible"
succInj :: forall n m. (n + 1) ~ (m + 1) => n :~: m
succInj = unsafeCoerce Refl
addComm :: forall n m. (n + m) :~: (m + n)
addComm = unsafeCoerce Refl
当然,您可以通过例如暴力破解来代替向 GHC 解释代数。更换 Odd
中的守卫 block , IsSucc
案例 Refl <- unsafeCoerce Refl :: n ~ (m' + m' + 2)
,对于其他人也是如此。但我不会这样做,因为这是否正确并不明显。相比之下,公理显然是正确的。通过用它们来做代数,你也证明了你的推理是正确的。
关于haskell - 固定大小的完美平衡树的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58775529/
我正在尝试实现 3 列固定-流体-固定布局。此外,布局的高度必须占据整个屏幕,使其看起来像从上到下的 3 个实心列。 总结: Left-column: fixed-width Center-col
我在网上搜索过,似乎找不到一个干净、简单、所有浏览器都友好的 3 列布局。 我希望有 3 列布局,左列固定为 200px,右列固定为 200px,中间列为剩余宽度,但最小宽度为 600px。所以整体最
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 8 年前。 Improve this q
我正在使用一些音频指纹技术来标记长录音中的歌曲。例如,在广播节目中的记录。指纹机制工作正常,但我在归一化(或下采样)方面遇到问题。 在这里您可以看到两首相同的歌曲,但波形不同。我知道我应该进行一些直流
为什么使用cout调用setprecision和fixed以及其他iomanip函数不像例如name.find('')plz这样的字符串函数 最佳答案 它们允许您以以下方式链接操作: cout <<
我正在尝试创建一个侧边栏,当用户向下滚动页面时,该侧边栏会跟随用户,并且我设法使用以下代码实现了效果: 标记 Javas
我正在尝试设置一些性能分析以及影响缓冲策略的运行时决策。我的应用程序收到一个指向由库(CUDA 或 OpenCL)分配的缓冲区的指针。 如何测试内存区域是否被页面锁定? 据我所知,POSIX 给了我们
我正在用 C# 编写一个 B+ 树实现,我为我的应用程序选择的树实现有一个非常特定的结构,它是缓存敏感的。为了实现这些属性,它对树节点有严格的布局策略。 我想要的只是使用 C# 的 fixed 来表达
我试图通过将 fragment 注入(inject)容器来在每个屏幕的底部放置一个广告 View 。通过使用 LinearLayout,我可以将 adview 置于操作栏下方的顶部。我已经尝试了 Re
我正在尝试创建一个导航稍微复杂的网站。我已经让导航看起来像我想要的初始加载,但现在我试图让它粘性导航到滚动顶部。我已经能够在导航栏到达顶部时创建一个类,但无法使其粘滞。每次我添加一个位置时,它都会跳回
首先,我正在寻找一个纯 CSS 解决方案。我可以使用 JavaScript 非常轻松地做到这一点,所以不要费心给我提示如何在 JS 中做到这一点。 我有一个包含 3 个容器的网页。其中 2 个是固定的
我猜这里有一种 super 特例。 我正在处理许多包含。现在我正在一个包含的内容文件中编码。我需要一个灯箱,它有一个 20% 的黑色背景覆盖整个页面,包括本身固定的标题,并在先前的 PHP 文件中设置
我正在尝试制作一个包含两个“固定”侧边栏图像和一个“固定”标题图像的页面。由于标题是固定的(距顶部 0 到 10%)。我不希望页眉图像与页面上的任何文本重叠。我尝试将段落标记定位为“相对”,并将其设置
我遇到了一个(水平)居中固定位置元素的解决方案,如下所示: element { width: 200px; position: fixed; left: 0; righ
我试图让我的网站主体具有固定的高度(我想!)。 无论如何,站点正文只是白色,边框大小为 1。基本上,正文的大小取决于其中的内容,例如,随着添加更多内容,它会自动调整大小。 我想要的是垂直滚动条,这样主
是否可以在 css 中创建 master-detail-states 布局? 我需要 3 个占位符: +---------------+-------+ | A | B
我的问题是,我是否必须在每个 Get/Post 请求之前单独请求检查 SSL Pinning OkHttpClient client = new OkHttpClient.Builder().cert
假设我有一个具有 N 个节点的常量(一旦构建就不会改变)平衡树,每个内部节点都有 p 个子节点。显然,访问节点的最坏情况是 logp(N)。但是访问 r 个节点的摊销成本呢?如果我们按升序访问它们(有
我知道会话固定是用php破解网站的方法。 会话固定是一种允许攻击者劫持有效用户会话的攻击 session fixation 但我不知道这可以防止我的项目中出现此问题。 是描述解决方案的方式或样本。 最
我在 jquery 砖石布局内有一个导航元素,我想将其修复到特定位置,比如右上角。是否可以这样做,以便所有其他元素都位于它周围? 诸如前置导航之类的东西.. 这是我的代码:http://jsfiddl
我是一名优秀的程序员,十分优秀!