我试图得到一些感觉MultiParamTypeClasses和FunctionalDependencies了,下面让我觉得一个明显的事情尝试:
{-# LANGUAGE MultiParamTypeClasses
, FunctionalDependencies
, TypeOperators #-}
import Data.Type.Equality
class C a b | a -> b
fob :: (C a b, C a b') => proxy a -> b :~: b'
fob _ = Refl
Run Code Online (Sandbox Code Playgroud)
不幸的是,这不起作用; GHC并未b ~ b'从该背景中得出结论.有没有办法使这项工作,或功能依赖不是"内部"可用?
目前,Jonathan S. 提出了拉取请求,根据Edward Kmett撰写的博客文章中的想法取代本自述文件中Data.IntMap解释的实现.
Jonathan S.开发的基本概念IntMap是a是一个看起来像这样的二叉树(为了保持一致性,我对他的开发做了一些细微的改动):
data IntMap0 a = Empty | NonEmpty (IntMapNE0 a)
data IntMapNE0 a =
Tip !Int a
| Bin { lo :: !Int
, hi :: !Int
, left :: !(IntMapNE0 a)
, right :: !(IntMapNE0 a) }
Run Code Online (Sandbox Code Playgroud)
在该表示中,每个节点具有指示包含在其中的最小和最大密钥的字段IntMapNE0.使用一点点摆弄可以将其用作PATRICIA trie.Jonathan指出,这种结构的范围信息几乎是它所需要的两倍.左侧或右侧脊柱将产生所有相同lo或hi边界.因此,他只是包括未经祖先决定的界限而削减了这些:
data IntMap1 a = Empty | NonEmpty { topLo :: !Int, child :: !(IntMapNE1 a) }
data IntMapNE1 a …Run Code Online (Sandbox Code Playgroud) 正如Typeclassopedia所证明的那样,从类别理论中引入的当前堆栈类似于历史的一个纠结事故,而不是一个美丽的连贯整体.
特别是,这使得跟踪正在发生的事情变得相当困难.
这些东西应该是什么样的,如果像向后兼容性,代码重复或易处理的短类型签名这样的小问题不是问题?
我正在考虑解压缩操作并意识到表达它们的一种方法是遍历一个Biapplicative仿函数.
import Data.Biapplicative
class Traversable2 t where
traverse2 :: Biapplicative p
=> (a -> p b c) -> t a -> p (t b) (t c)
-- Note: sequence2 :: [(a,b)] -> ([a], [b])
sequence2 :: (Traversable2 t, Biapplicative p)
=> t (p b c) -> p (t b) (t c)
sequence2 = traverse2 id
instance Traversable2 [] where
traverse2 _ [] = bipure [] []
traverse2 f (x : xs) = bimap (:) (:) (f x) <<*>> …Run Code Online (Sandbox Code Playgroud) 对于任何Applicative实例,一旦<*>写入,pure是唯一确定的。假设您有pure1和pure2,两者都遵守法律。然后
pure2 f <*> pure1 y = pure1 ($ y) <*> pure2 f -- interchange for pure1
pure2 id <*> pure1 y = pure1 ($ y) <*> pure2 id -- specialize f to id
pure1 y = pure1 ($ y) <*> pure2 id -- identity for pure2
pure1 y = fmap ($ y) (pure2 id) -- applicative/fmap law for pure1
pure1 y = pure2 ($ y) <*> pure2 id -- …Run Code Online (Sandbox Code Playgroud) 该Applicative实例Data.Sequence通常性能非常好。几乎所有的方法在时间和空间上都是渐进渐近最优的。也就是说,给定完全强制/实现的输入,可以在渐近最优的时间和内存驻留中访问结果的任何部分。还有一个例外:(<*). 我目前只知道两种实现方式:
默认实现
xs <* ys = liftA2 const xs ys
Run Code Online (Sandbox Code Playgroud)
这个实现需要O(|xs| * |ys|)时间和空间来完全实现结果,但只O(log(min(k, |xs|*|ys|-k)))访问k结果的第 th 个元素。
“一元”实现
xs <* ys = xs >>= replicate (length ys)
Run Code Online (Sandbox Code Playgroud)
这只需要O(|xs| * log |ys|)时间和空间,但它不是增量的;访问结果的任意元素需要O(|xs| * log |ys|)时间和空间。
长期以来,我一直认为应该有可能拥有我们的蛋糕并吃掉它,但我从来没有能够很好地处理我脑海中的碎片以达到目标。要做到这一点似乎需要从的实现思路(而不是实际的代码)的组合liftA2和replicate。如何才能做到这一点?
注意:它肯定不会有必要结合像什么rigidify的机制liftA2。类似replicate的部分肯定应该只产生我们rigidify用来从用户提供的树中获得的那种“刚性”结构。
任务完成!我设法找到了一种方法。不幸的是,这对我来说有点太复杂了,无法理解正在发生的一切,而且代码……相当不透明。我会赞成并接受对我所写内容的一个很好的解释,并且也会很高兴地接受关于 GitHub …
我有一个客户端 - 服务器应用程序,它通过互联网使用firebird服务器2.5.我遇到了安全访问FB数据库的问题,并且作为第一个尝试通过在应用程序中集成隧道解决方案(更准确地说是STunnel软件)来解决这个问题.但是,这个approch受到许多方面的影响: - 这会在客户端/服务器端增加更多的资源消耗(CPU,内存,线程), - 软件部署成为一个严重的问题,因为STunnel软件被写为WinNT服务,而不是Dll或组件(WinNT服务需要安装的管理员权限),我的客户端应用程序需要在没有安装的情况下运行!
所以,我决定用喇叭(或者当我们谈论Firebird时用羽毛抓鸟)来取公牛.我已经下载了Firebird 2.5源代码并直接在其低级通信层(INET套接字层)中注入安全隧道化代码.现在,加密/解密由firebird引擎直接为每个TCP/IP数据包完成.
您如何看待这种方法与外部隧道化?
在我的应用程序中,我想创建一个泛型方法,它创建一个取决于给定类型T的对象数组.
我创建了以下功能:
func getArray<T : ROJSONObject>(key:String) -> T[] {
var elements = T[]()
for jsonValue in getValue(key).array! {
var element = T()
element.jsonData = jsonValue
elements.append(element)
}
return elements
}
Run Code Online (Sandbox Code Playgroud)
现在我想在调用方法时传递类型,因此它确实知道它应该在内部创建哪种类型.我认为在Java和C#中你可以使用这样的方法:
object.getArray<Document>("key")
Run Code Online (Sandbox Code Playgroud)
当我这样称呼它时,我总是得到错误:
Cannot explicitly specialize a generic function
Run Code Online (Sandbox Code Playgroud)
所以我的修复是定义一个包含类型T实例的附加参数,因此它会自动检测类型:
func getArray<T : ROJSONObject>(key:String, type:T) -> T[] {
var elements = T[]()
for jsonValue in getValue(key).array! {
var element = T()
element.jsonData = jsonValue
elements.append(element)
}
return elements
}
Run Code Online (Sandbox Code Playgroud)
没有传递未使用的实例,是否真的没有其他方法可以获得该行为?还是我误解了什么?
进一步测试
在jtbandes的回答后,我做了一些测试.我试图通过as在调用中添加来强制Type .
class Person {
init() { …Run Code Online (Sandbox Code Playgroud) 假设我有
data Foo a = Foo !Int a [a] | Bar [a]
Run Code Online (Sandbox Code Playgroud)
所以Foo构造函数的第一个参数是严格的,将被解压缩.进一步假设我正在传递Foo n给更高阶的函数f并且f没有内联(因此Foo n实际上已经传递).我得到的核心-O2表示n被盒装然后传递给Foo,结果传递给f.我的问题:我打电话会更好吗?
f (\a b -> Foo n a b)
Run Code Online (Sandbox Code Playgroud)
避免拳击n?或者会导致其他一些性能问题?
我其实是想要定义
foo' !n = \a b -> Foo n a b
Run Code Online (Sandbox Code Playgroud)
并打电话f (foo' n),我认为应该做同样的事情,但我想最好特别问一下.
该MonadBaseControl课程提供的法律很少。为了得到我想要的东西,我还需要一个:
forall f q. f <$> liftBaseWith q
= liftBaseWith $ \runInBase -> fmap f (q runInBase)
Run Code Online (Sandbox Code Playgroud)
我极其模糊的直觉表明,这是自然的(从某种意义上来说),甚至可能是由Functor定律,参数化和成文法则的某种组合而产生的MonadBaseControl。是这样吗 如果不是,是否有任何违反法律的“合理”实例?
注意:我还问过这个问题的缩写形式是GitHub issue。
haskell ×8
applicative ×2
typeclass ×2
bifunctor ×1
database ×1
finger-tree ×1
firebird ×1
generics ×1
performance ×1
security ×1
swift ×1
traversal ×1
tunnel ×1
types ×1