小编jam*_*idh的帖子

Data.Text vs. Rope

我一直在研究绳索作为Data.Text的替代品,我喜欢我所看到的以至于我现在不得不问这个问题....有没有哪种情况下Data.Text会是更好的选择?

以下是引导我的要点(如果我错在任何这些上,请纠正我) -

  1. 单个叶节点绳内部(几乎)相同的东西作为一个Data.Text对象.单节点绳索与文本的开销很小,只是用于区分分支或叶子的单个位标志.如果你真的想要Data.Text,只需使用未分裂的绳索.

  2. 复杂性在绳索插入/删除(log(N)vs N)中普遍相等或更好,通过索引得到(log(N)/ N取决于树的深度对N).

  3. 我已经读过绳索的成功证明是c中的混合包,因为线程安全代码损害了性能.然而,这些问题在不可变的Haskell中无关紧要.事实上,在我看来,因此,Haskell和绳索是彼此的理想选择.

再次,就像我以前的类似问题一样,我对结构的抽象质量更感兴趣,而不是当前的情况(库使用,代码的强化程度等).如果你明天重写了Haskell库,你会用Data.Rope替换Data.Text吗?

haskell

14
推荐指数
1
解决办法
377
查看次数

编写Monad Transformer,它真的需要这么多硬编码实例

我是monad变换器的长期用户,第一次使用monad变换器编写器....而且我觉得我做了一些不必要的事情.

我们正在开发一个具有多个数据库表的项目,并且将该集合硬编码到不同的monad堆栈变得笨重,所以我们决定将其分解为不同的可插入monad变换器,允许我们在功能类型级别进行选择,如下所示

doSomething::(HasUserTable m, HasProductTable m)=>Int->m String
Run Code Online (Sandbox Code Playgroud)

(HasXTable是类,XTableT是具体的monad变换器).这些独立的monad变压器可以完全模块化的方式插入或移除,并存储DB手柄,需要ResourceT等....

我的第一次尝试是将ReaderT包裹起来,它将用于保存数据库句柄.很明显,这是行不通的,因为ReaderT(和StateT等)不能在不使用硬编码"升力"链的情况下堆叠,从而破坏了堆叠元件的可插拔模块性.

唯一的解决方案似乎是编写完全独立的ReaderT monad副本,每个副本允许访问较低级别的其他副本.这是有效的,但解决方案充满了样板代码,就像这样

class HasUserTable m where
    getUser::String->m User

newtype UserTableT m r = UserTableT{runUserTableT::String->m r}

--Standard monad instance stuff, biolerplate copy of ReaderT
instance Functor m=>Functor (UserTableT m) where....
instance Applicative m=>Applicative (UserTableT m) where....
instance Monad m=>Monad (UserTableT m) where....
instance Monad m=>HasUserTable (UserTableT m) where....

--Gotta hardcode passthrough rules to every other monad transformer
--in the world, mostly using "lift"....
instance MonadTrans BlockCacheT where....
instance (HasUserTable m, Monad m)=>HasUserTable …
Run Code Online (Sandbox Code Playgroud)

monads haskell monad-transformers

12
推荐指数
1
解决办法
481
查看次数

`Data.Text`对`Data.Vector.Unboxed Char`

内部的方式Data.TextData.Vector.Unboxed Char工作有什么不同吗?为什么我会选择一个而不是另一个?

我一直以为这是很酷的是哈斯克尔定义String[Char].是否有一个原因的东西analagous对于没有这样做Text,并Vector Char

使它们相同肯定会有一个优势......可以编写Text-y和Vector-y工具以在两个阵营中使用.想象一下Ints的绳索,或者扑克牌上的正则表达.

当然,我知道可能有历史原因,我理解大多数现有的图书馆使用的Data.Text不是Vector Char,所以有许多实际的理由支持一个而不是另一个.但是我更感兴趣的是了解抽象的品质,而不是我们碰巧在的当前状态......如果整个事情明天被重写,那么统一两者会更好吗?

编辑,更多信息 -

把东西放到透视图中 -

  1. 根据这个页面http://www.haskell.org/haskellwiki/GHC/Memory_Footprint,GHC为你的程序中的每个Char使用16个字节!

  2. Data.Text不是O(1)索引,它是O(n).

  3. Ropes(文本周围的二叉树)也可以包含字符串....它们具有更好的索引/插入/删除复杂性,尽管取决于节点的数量和树的平衡,索引可能接近于Text的索引.

这是我从这里得到的 -

  1. TextVector Char是不同的内部....

  2. 如果您不关心性能,请使用String.

  3. 如果性能很重要,则默认使用Text.

  4. 如果需要快速索引字符,并且您不介意大量内存开销(最多16倍),请使用Vector Char.

  5. 如果要插入/删除大量数据,请使用Ropes.

haskell

11
推荐指数
2
解决办法
599
查看次数

当数字常数超出范围时,为什么GHC不抱怨

GHC默默地忽略数值常量中的超出范围位.

这种行为导致我今天与一个相当奇怪的bug搏斗:

[0..256]::[Word8] -- evaluates to [0]!
Run Code Online (Sandbox Code Playgroud)

我知道是什么导致了这个错误(在rot256世界中256 == 0)....我感兴趣的是为什么GHC/Haskell的设计不会在编译时抱怨它.

(这种行为对于Int也是如此 - 例如,18446744073709551617::Int = 1).

我已经习惯了Haskell捕捉琐碎的编译时间问题,当我不得不追踪它时,我感到很惊讶.

haskell

9
推荐指数
1
解决办法
200
查看次数

1GB Vector,会将Vector.Unboxed给麻烦,Vector.Storable会给你带来麻烦吗?

我们需要在内存中存储大量1GB的连续字节很长一段时间(几周到几个月),并且正在尝试选择一个Vector/Array库.我有两个问题,我无法找到答案.

  1. Vector.Unboxed似乎存储堆上的底层字节,可以由GC随意移动....定期移动1GB的数据将是我想要避免的.

  2. Vector.Storable通过将基础字节存储在c堆中来解决此问题.但我读过的所有内容似乎都表明这只是用于与其他语言(主要是c)进行通信.是否有一些原因我应该避免使用Vector.Storable进行内部Haskell使用.

如果有意义,我愿意接受第三种选择!

haskell

9
推荐指数
1
解决办法
140
查看次数

Esqueleto:如何使用联接删除项目

使用esqueleto可以进行以下查询吗?

DELETE Table1
FROM Table1
INNER JOIN Table2 ON Table1.ID = Table2.ItemID
Run Code Online (Sandbox Code Playgroud)

我试过了:

delete $ 
  from $ \(table1 `InnerJoin` table2) -> 
    on (table1 ^. Table1ID  ==. table2 ^. Table2ItemID)
Run Code Online (Sandbox Code Playgroud)

奇怪的是,它产生了我在Haskell中见过的唯一运行时错误之一

ERROR:  syntax error at or near "INNER"
LINE 2: FROM "table1" INNER JOIN "table2" ON "tab...
Run Code Online (Sandbox Code Playgroud)

(基本上,不幸的DELETE是错过了"table1")

我也尝试在monad中添加一个返回值,与select一样可能会添加该值.但这失败了,因为删除需要monad类型m ().

这可能是Esqueleto遗失的吗?

sql haskell esqueleto

9
推荐指数
1
解决办法
325
查看次数

具有高效插入/删除的"列表"

我正在寻找在索引i处插入/删除日志(N)的"列表".我把单词"List"放在引号中,因为我并不是说它是一个真正的Haskell List,而是任何带有一堆对象的有序容器(事实上,它可能需要内部的某种树).我很惊讶我还没有找到一个很好的解决方案....

这是我迄今为止最好的解决方案 - 使用Data.Sequence这两个函数.

doInsert position value seq = before >< ( value <| after)
     where
     (before, after) = splitAt position seq

doDelete position seq = before >< (drop 1 after)
     where
     (before, after) = splitAt position seq
Run Code Online (Sandbox Code Playgroud)

虽然这些在技术上都是log(N)函数,但感觉就像我为每个插入/删除做了一堆额外的东西....换句话说,这对于K更大的K来说就像K*log(N)一样比应该的.另外,由于我必须自己定义这些内容,我觉得我正在使用Sequence来实现它不适合的东西.

有没有更好的办法?

这是一个相关的问题(尽管它只涉及Sequences,我很乐意使用其他任何东西):为什么Data.Sequence没有`insert'或`insertBy',我该如何有效地实现它们?

是的,这个问题与我几天前发布的另一个问题有关:大量的XML编辑

haskell

8
推荐指数
1
解决办法
411
查看次数

没有使用哪些cabal包

如果我用GHC发出警告,它会警告我哪些进口没有被使用....

是否有类似的命令告诉我哪些文件build-depends没有被使用<project>.cabal

haskell cabal

8
推荐指数
1
解决办法
103
查看次数

有效地将字节打包成整数?

这是一开始看起来容易的问题之一,但我已经研究了一段时间,但找不到答案....

我需要将字节列表(ie- Word8s)转换为任意长度的数字(即-a Integer).例如

intPack::[Word8]->Integer
intPack [1] = 1
intPack [1, 0] = 256
showHex (intPack [1,2,3,4,5,6,7,8,9,10,11]) "" = "102030405060708090a0b"
Run Code Online (Sandbox Code Playgroud)

一个缓慢的解决方案很容易编写(请参阅如何将ByteString转换为Int并处理字节序的答案 )

intPack = foldl (\v -> ((v*256) +)) 0
Run Code Online (Sandbox Code Playgroud)

....但是我对此畏缩,所有额外的乘法和加法,加上在中间创建的一串无用的整数,只是为了(可能)获得与打包到Integer类型的内部结构中相同的字节.

当然,我不知道Integer如何存储其数据的细节(也许它比在可变长度数组中保存字节更复杂......比如使用flags来表示数字的长度,比如utf -8在编码字符时执行).至少知道intPack上面的内容就像它一样好......然后我可以停止我的研究,咬一口(或者更确切地说是字节:)的子弹,继续前进.

haskell

6
推荐指数
1
解决办法
229
查看次数

如何在堆栈中使用"-ddump-minimal-imports"

我是堆栈的忠实粉丝,我已经从我的机器上完全删除了任何独立的cabal和ghc可执行文件(让堆栈在它自己神秘的〜/ .stack /目录中安装它需要的任何东西)....

但是,看起来有些标志在堆栈下无法正常工作.例如,我想使用-ddump-minimal-imports.在cabal这将是

cabal build --ghc-option=-ddump-minimal-imports
Run Code Online (Sandbox Code Playgroud)

明显的翻译是

stack build --ghc-options -ddump-minimal-imports
Run Code Online (Sandbox Code Playgroud)

这运行,但只生成可执行文件(据我所知,至少......也许输出是在神秘的〜/ .stack目录中的某个地方).

有没有办法做到这一点?

haskell haskell-stack

6
推荐指数
1
解决办法
264
查看次数