- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在处理这种形状的数据类型,使用线性
中的V
:
type Foo n = V (n * 3) Double -> Double
将其固定在 n
上非常重要,因为我希望能够确保在编译时传递正确数量的元素。这是我的程序的一部分,已经运行良好,与我在这里所做的事情无关。
对于任何 KnownNat n
,我可以生成一个 Foo n
来满足我的程序所需的行为。就这个问题而言,这可能是一些愚蠢的事情,例如
mkFoo :: KnownNat (n * 3) => Foo n
mkFoo = sum
或者更有意义的例子,它可以生成一个相同长度的随机V
,并在两者上使用dot
。这里的 KnownNat
约束是多余的,但实际上,需要它来创建 Foo
。我制作一个 Foo 并将其用于我的整个程序(或多个输入),因此这保证了我无论何时使用它,我都会在具有相同长度的东西上使用,并且在相同长度的东西上使用Foo
的结构决定了。
最后,我有一个为 Foo
提供输入的函数:
bar :: KnownNat (n * 3) => Proxy n -> [V (n * 3) Double]
bar 实际上是我使用 n * 3
作为类型函数而不是手动扩展它的原因。原因是 bar
可能通过使用三个长度为 n
的向量并将它们全部附加在一起作为长度为 n * 3
的向量来完成其工作。此外,从语义上来说,n
对于函数来说是比 n * 3
更有意义的参数。这也让我禁止使用不正确的值,例如 n
不是 3 的倍数等。
现在,以前,只要我在开始时定义了类型同义词,一切都会正常工作:
type N = 5
然后我可以将 Proxy::Proxy N
传递给 bar
,并使用 mkFoo::Foo N
。一切都运行良好。
-- works fine
doStuff :: [Double]
doStuff = let inps = bar (Proxy :: Proxy N)
in map (mkFoo :: Foo N) inps
但现在我希望能够在运行时通过从文件或命令行参数加载信息来调整 N
。
我尝试通过调用 reflectNat
来做到这一点:
doStuff :: Integer -> Double
doStuff n = reflectNat 5 $ \pn@(Proxy :: Proxy n) ->
let inps = bar (Proxy :: Proxy n)
in map (mkFoo :: Foo n) inps
但是...bar
和 mkFoo
需要 KnownNat (n * 3)
,但 reflectNat
只是给出我KnownNat n
。
有什么方法可以概括 reflectNat
给我的证明来满足 foo
吗?
最佳答案
所以,三个月后,我一直在寻找实现这一目标的好方法,但我最终确定了一个非常简洁的技巧,不需要任何一次性的新类型;它涉及使用 constraints 中的 Dict
图书馆;你可以轻松地写一个:
natDict :: KnownNat n => Proxy n -> Dict (KnownNat n)
natDict _ = Dict
triple :: KnownNat n => Proxy n -> Dict (KnownNat (n * 3))
triple p = reifyNat (natVal p * 3) $
\p3 -> unsafeCoerce (natDict p3)
一旦获得Dict (KnownNat (n * 3)
,您就可以对其进行模式匹配以获取范围内的(n * 3)
实例:
case triple (Proxy :: Proxy n) of
Dict -> -- KnownNat (n * 3) is in scope
您实际上也可以将它们设置为通用:
addNats :: (KnownNat n, KnownNat m) => Proxy n -> Proxy m -> Dict (KnownNat (n * m))
addNats px py = reifyNat (natVal px + natVal py) $
\pz -> unsafeCoerce (natDict pz)
或者,您可以将它们设为运算符,然后使用它们来“组合”字典:
infixl 6 %+
infixl 7 %*
(%+) :: Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat (n + m))
(%*) :: Dict (KnownNat n) -> Dict (KnownNat m) -> Dict (KnownNat (n * m))
您可以执行以下操作:
case d1 %* d2 %+ d3 of
Dict -> -- in here, KnownNat (n1 * n2 + n3) is in scope
我已经将其封装在一个不错的库中, typelits-witnesses 我一直在使用。谢谢大家的帮助!
关于haskell - 我可以让 KnownNat n 来暗示 KnownNat (n * 3) 等吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32839389/
我正在处理这种形状的数据类型,使用线性中的V: type Foo n = V (n * 3) Double -> Double 将其固定在 n 上非常重要,因为我希望能够确保在编译时传递正确数量的元素
我一直在尝试(未成功)在运行时的 haskell 中创建一个“对象”*,其类型在运行时使用依赖类型定义。 我在关注 this tutorial on dependent types他们用来在运行时传递
我正在试验单例库,发现一个我不明白的案例。 {-# LANGUAGE GADTs, StandaloneDeriving, RankNTypes, ScopedTypeVariables, Flexi
关于KnownNats,我想知道我是否也可以吃蛋糕。 .我可以编写使用 Nats 的代码吗?可能都是KnownNats和 UnknownNats (SomeNats?)。 例如,如果我有一个依赖类型的
我刚刚发现了 super 棒的 Haskell 库 Numeric.LinearAlgebra.Static来自 hmatrix包裹。 现在我实现了一个函数,它将矩阵 A 转换为向量 B 和另一个矩阵
我一直在尝试实现 Chinese Remainder Theorem ,对于只有两个方程的特定情况,使用Data.Modular包裹。我的想法是,我可以仅用一个模数指定每个方程(使用数字a (mod
我发现了两种在运行时将 Integer 提升为 Nat(或 KnownNat,我还没有得到区分)的方法,使用 TypeLits 和 Proxy(Data.Proxy 和 GHC.TypeLits),或
在 singletons 包中,函数 withKnownNat有以下奇怪的类型签名: withKnownNat::Sing n -> (KnownNat n => r) -> r。 KnownNat
我是一名优秀的程序员,十分优秀!