小编Dav*_*aly的帖子

Attoparsec在大型"接听"呼叫上分配了大量内存

所以我正在编写一个数据包嗅探应用程序.基本上我想让它嗅探tcp会话,然后解析它们是否是http,如果它们是,如果它们有正确的内容类型等,请将它们保存为我的硬盘上的文件.

所以,为此,我希望它有效率.由于当前的http库是基于字符串的,我将处理大文件,而我只需要解析http响应,我决定在attoparsec中自己编写.

当我完成我的程序时,我发现当我使用其中的wav文件解析9 meg的http响应时,当我对其进行分析时,它在尝试解析http响应的主体时分配了一大堆内存.当我查看HTTP.prof时,我看到一些行:

httpBody              Main                                                 362           1   0.0    0.0    93.8   99.3

 take                 Data.Attoparsec.Internal                             366        1201   0.0    0.0    93.8   99.3
     takeWith            Data.Attoparsec.Internal                             367        3603   0.0    0.0    93.8   99.3
      demandInput        Data.Attoparsec.Internal                             375         293   0.0    0.0    93.8   99.2
       prompt            Data.Attoparsec.Internal                             378         293   0.0    0.0    93.8   99.2
        +++              Data.Attoparsec.Internal                             380         586  93.8   99.2    93.8   99.2

正如你所看到的,httpbody中的某个地方,被称为1201次,导致500+(+++)串行的字节串联,这导致了大量的内存分配.

这是代码.N只是http响应的内容长度(如果有的话).如果没有,它只会尝试采取一切.

我希望它返回一个1000左右的字符字节串的惰性字节串,但即使我把它改为只需要n并返回一个严格的字节串,它仍然有它的那些分配(它使用14 gig的内存).


httpBody n = do
  x <- if n > 0
    then AC.take n
    else AC.takeWhile (\_ -> True)
  if B.length x == 0
    then return …
Run Code Online (Sandbox Code Playgroud)

parsing haskell attoparsec

19
推荐指数
1
解决办法
1179
查看次数

如何捕获(并忽略)对错误函数的调用?

我很惊讶我无法在任何地方找到答案.

我正在编写一个roguelike,我正在使用来自hackage的ncurses库,这是ncurses库的一个非常好的包装器.现在ncurses有这个怪癖,如果你试图写下右下角,它会这样做,然后它会尝试将光标移动到下一个角色,然后失败,因为没有地方可以将它移动到.它返回一个您只能忽略的错误值.

我的问题是haskell ncurses库编写者尽职地检查所有调用的任何错误,当有一个时,他调用:error"drawText:etc etc.".

在其他语言中,比如c或python,为了解决这个问题,你不得不忽略错误或捕获并忽略异常,但对于我的生活,我无法弄清楚如何在haskell中做到这一点.错误功能是不可恢复的吗?

我将在本地修改库,以便在必要时不检查该函数的错误,但我讨厌这样做.我也对任何可以让我在不移动光标的情况下绘制最后一个字符的解决方法持开放态度,但我不认为这是可能的.

haskell exception-handling exception referential-transparency

17
推荐指数
2
解决办法
4290
查看次数

我不明白yesod中这类家庭的东西是什么

我浏览了yesod书和来源,并了解了一切如何运作.但在我写自己的东西之前,脚手架网站中有一件事我不明白.

所以我在一个网站"copywww"上加工,在文件CopyWWWState.hs中有代码:

instance YesodPersist CopyWWWState where
    type YesodDB CopyWWWState = SqlPersist
    runDB db = liftIOHandler
             $ fmap connPool getYesod >>= Settings.runConnectionPool db

instance YesodAuth CopyWWWState where
    type AuthId CopyWWWState = UserId

    -- Where to send a user after successful login
    loginDest _ = RootR
    -- Where to send a user after logout
    logoutDest _ = RootR

    getAuthId creds = runDB $ do
        x <- getBy $ UniqueUser $ credsIdent creds
        case x of
            Just (uid, _) -> return $ Just …
Run Code Online (Sandbox Code Playgroud)

haskell yesod

13
推荐指数
1
解决办法
743
查看次数

具有代数类型的镜头包

我用镜头包编码.一切都很顺利,直到我试图访问代数类型的某个字段:

import Control.Lens

data Type = A { _a :: Char } | B

makeLenses ''Type

test1 = _a (A 'a')
test2 = (A 'a') ^. a

No instance for (Data.Monoid.Monoid Char)
  arising from a use of `a'
Possible fix:
  add an instance declaration for (Data.Monoid.Monoid Char)
In the second argument of `(^.)', namely `a'
In the expression: (A 'a') ^. a
In an equation for `test2': test2 = (A 'a') ^. a
Run Code Online (Sandbox Code Playgroud)

我可以选择_a,但我的真实程序中的数据类型更深,我打算使用镜头来降低我必须做的工作量.我一直在查看镜头库,但那里有很多,我不确定他是否处理过这种情况,或者它只是镜头库不支持的东西.

作为旁注,如果我实际上使用类似String的monoid作为数据类型而不是Char,那么它会编译并给出正确的答案,我不知道为什么.

编辑:在阅读了hammar的评论后,我尝试了这个,这有效:

test2 = (A 'a') …
Run Code Online (Sandbox Code Playgroud)

haskell lenses

13
推荐指数
1
解决办法
313
查看次数

我似乎无法弄清楚与类混合的类型变量

我非常理解其他语言的3/4,但每次我在我的代码中以有意义的方式使用类时,我都会得到根深蒂固.

为什么这个非常简单的代码不起作用?

data Room n = Room n n deriving Show

class HasArea a where
  width :: (Num n) => a -> n

instance (Num n) => HasArea (Room n) where
  width (Room w h) = w
Run Code Online (Sandbox Code Playgroud)

因此,房间宽度由整数或浮点数表示,我不想在此时限制它.类和实例都将n类型限制为Nums,但它仍然不喜欢它,我收到此错误:

Couldn't match expected type `n1' against inferred type `n'
  `n1' is a rigid type variable bound by
       the type signature for `width' at Dungeon.hs:11:16
  `n' is a rigid type variable bound by
      the instance declaration at Dungeon.hs:13:14
In the expression: w
In …
Run Code Online (Sandbox Code Playgroud)

haskell

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

如何在Parsec中使用Control.Monad.State?

我很惊讶我找不到任何关于此的信息.我必须是唯一一个遇到任何麻烦的人.

所以,假设我有一个破折计数器.我希望它计算字符串中的破折号数,并返回字符串.假装我给出了一个使用parsec状态处理无效的示例.所以这应该工作:

dashCounter = do
  str <- many1 dash
  count <- get
  return (count,str)


dash = do
  char '-'
  modify (+1)
Run Code Online (Sandbox Code Playgroud)

事实上,这是编译.好的,我尝试使用它:

:t parse dashCounter "" "----"
parse dashCounter "" "----"
  :: (Control.Monad.State.Class.MonadState
        t Data.Functor.Identity.Identity,
      Num t) =>
     Either ParseError (t, [Char])
Run Code Online (Sandbox Code Playgroud)

好的,这是有道理的.它应该返回状态和字符串.凉.

>parse dashCounter "" "----"

<interactive>:1:7:
    No instance for (Control.Monad.State.Class.MonadState
                       t0 Data.Functor.Identity.Identity)
      arising from a use of `dashCounter'
    Possible fix:
      add an instance declaration for
      (Control.Monad.State.Class.MonadState
         t0 Data.Functor.Identity.Identity)
    In the first argument of `parse', namely `dashCounter'
    In the …
Run Code Online (Sandbox Code Playgroud)

haskell parsec

11
推荐指数
3
解决办法
2153
查看次数

你如何以贪婪的方式使用parsec?

在我的工作中,我遇到了很多粗糙的SQL,我有一个明智的想法,即编写一个程序来解析sql并将其打印出来.我很快就完成了大部分工作,但我遇到了一个我不知道如何解决的问题.

所以让我们假装sql是"从1中选择foo".我的想法是总是有一个关键字后跟数据,所以我要做的就是解析一个关键字,然后在下一个关键字之前捕获所有乱码并存储以供以后清理,如果值得的话.这是代码:

import Text.Parsec
import Text.Parsec.Combinator
import Text.Parsec.Char
import Data.Text (strip)

newtype Statement = Statement [Atom]
data Atom = Branch String [Atom] | Leaf String deriving Show

trim str = reverse $ trim' (reverse $ trim' str)
  where
    trim' (' ':xs) = trim' xs
    trim' str = str

printStatement atoms = mapM_ printAtom atoms
printAtom atom = loop 0 atom 
  where
    loop depth (Leaf str) = putStrLn $ (replicate depth ' ') ++ str
    loop depth (Branch str atoms) = …
Run Code Online (Sandbox Code Playgroud)

parsing haskell

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

无法在单身人士图书馆的两个存在中推断出KnownNat

我正在试验单身人士图书馆,我发现了一个我不理解的案例.

{-# LANGUAGE GADTs, StandaloneDeriving, RankNTypes, ScopedTypeVariables,
FlexibleInstances, KindSignatures, DataKinds, StandaloneDeriving  #-}

import Data.Singletons.Prelude
import Data.Singletons.TypeLits

data Foo (a :: Nat) where
 Foo :: Foo a
  deriving Show

data Thing where
  Thing :: KnownNat a => Foo a -> Thing

deriving instance Show Thing

afoo1 :: Foo 1
afoo1 = Foo 

afoo2 :: Foo 2
afoo2 = Foo 

athing :: Thing
athing = Thing afoo1

foolen :: forall n. KnownNat n => Foo n -> Integer
foolen foo =
  case …
Run Code Online (Sandbox Code Playgroud)

haskell existential-type dependent-type

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

如何将基于拉力的管道转变为基于推力的管道?

默认情况下,管道是基于拉的.这是由于实施的操作员>->,通过+>>bind操作员是他的拉动类别的有意义的操作员.我的理解是,这意味着如果你有代码producer >-> consumer,首先会调用消费者的身体,然后一旦等待数据,就会调用生产者.

我见过的在pipes文档在这里,你可以使用代码(reflect .)Pipes.Core把一个基于拉管道进入基于推送管.这意味着(纠正我,如果我错了)在上面的代码中producer >-> consumer,生产者先运行,产生一个值,然后消费者试图消费.这似乎非常有用,我想知道如何做到这一点.

我在这里的讨论中也看到没有基于推送的对应物,>->因为它很容易转换任何管道(我假设有反射?),但我无法真正想出如何做或找到任何例子.

这是我尝试过的一些代码:

stdin :: Producer String IO r
stdin = forever $ do
  lift $ putStrLn "stdin"
  str <- lift getLine
  yield str

countLetters :: Consumer String IO r
countLetters = forever $ do
  lift $ putStrLn "countLetters"
  str <- await
  lift . putStrLn . show . length $ str

-- …
Run Code Online (Sandbox Code Playgroud)

haskell haskell-pipes

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

在aeson中,您如何编码而不会产生科学记数法?

我已经解析了大量的json,操纵了一些值,我想把它写回来.Aeson将数字解码为科学,但是当它编码时,默认情况下,科学在很多情况下用科学记数法显示数字,而且aeson没有提供任何我可以看到的改变它的方法.

> decode "[\"asdf\", 1, 1.0, 1000000000.1, 0.01]" :: Maybe Value
Just (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])

encode (Array [String "asdf",Number 1.0,Number 1.0,Number 1.0000000001e9,Number 1.0e-2])
"[\"asdf\",1,1,1.0000000001e9,1.0e-2]"

> encode (Array [String "asdf", Number 1, Number 1.0, Number 1000000000.1, Number 0.01])
"[\"asdf\",1,1,1.0000000001e9,1.0e-2]"
Run Code Online (Sandbox Code Playgroud)

如何以更广泛接受的格式用其他语言可以使用的数字写出我的值?让我假装我不关心精度损失或整数溢出.科学软件包具有以这种方式格式化数字的方法,aeson恰好没有使用它.

>formatScientific Fixed Nothing (0.01)
"0.01"

>formatScientific Fixed Nothing (1000000000.1)
"1000000000.1"
Run Code Online (Sandbox Code Playgroud)

haskell aeson

5
推荐指数
1
解决办法
237
查看次数