小编Dav*_*rak的帖子

使单个函数在列表,ByteStrings和文本(以及可能的其他类似表示)上工作

我正在编写一个函数,可以在一系列任意符号中进行搜索.我想使它足够通用,以便它可以在列表,Foldables以及ByteStrings和Texts上运行.将其概括Foldable为简单.但是如何包含ByteStrings和Texts?当然我可以转换ByteString成一个列表,然后调用我的功能,但我会失去所有的优势ByteString.

举一个具体的例子,假设我们想要制作直方图函数:

import Control.Monad.State
import qualified Data.Foldable as F
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Data.Word
import qualified Data.ByteString as B
import qualified Data.Text as T

type Histogram a = Map a Int

empty :: (Ord a) => Histogram a
empty = Map.empty

histogramStep :: (Ord a) => a -> Histogram a -> Histogram a
histogramStep k = Map.insertWith (+) k …
Run Code Online (Sandbox Code Playgroud)

text haskell fold bytestring lenses

9
推荐指数
3
解决办法
592
查看次数

是否可以在运行时生成并运行TemplateHaskell生成的代码?

是否可以在运行时生成并运行TemplateHaskell生成的代码?

在运行时使用C,我可以:

  • 创建函数的源代码,
  • 调用gcc将其编译为.so(linux)(或使用llvm等),
  • 加载.so和
  • 调用该函数.

与模板Haskell类似的事情是否可能?

c haskell runtime ghc-api template-haskell

8
推荐指数
2
解决办法
478
查看次数

符号与let中的模式匹配

我最近在使用threepenny-gui时遇到了一个错误 ,它通过将符号中的模式匹配的代码更改为<-与let符号的模式匹配来解决.

在这两种模式匹配形式之间进行转换时,我是否应该期望改变行为?

具体如下代码:

在IO monad中:

Just events <- Map.lookup elid <$> readMVar sElementEvents
Run Code Online (Sandbox Code Playgroud)

改为:

mevents <- Map.lookup elid <$> readMVar sElementEvents
let Just events = mevents
Run Code Online (Sandbox Code Playgroud)

这是一个提交的链接,为我解决了问题:https: //github.com/Davorak/threepenny-gui/commit/fbf6cbe25875fafdc64f7a111ddebf485b45143b

其他平台细节:os:10.8.5 ghc:7.6.3

编辑:添加了这个发生在IO monad的事实

haskell pattern-matching do-notation threepenny-gui

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

为什么Mathematica会破坏模块中的正常范围规则?

正如在最近一篇文章中所指出的那样,范围内的模块不能按预期工作.

该线程的一个例子是:

Module[{expr},
 expr = 2 z;
  f[z_] = expr;
  f[7]]
(*2 z*)
Run Code Online (Sandbox Code Playgroud)

但以下工作几乎与预期一致.

Module[{expr},
 expr = 2 z;
  Set@@{f[z_], expr};
  f[7]]
(*14*)
Run Code Online (Sandbox Code Playgroud)

什么语言设计考虑使wolfram选择此功能?

编辑:请参阅Jefromi的第一条评论我将z从局部变量更改为not并忘记更改输出.它不会影响问题.

编辑2:Michael Pilat的观点似乎是Block和Module具有不同的功能.我想我理解他的观点,但我认为这与我的问题是正交的.所以这是一个更新.

我可以在笔记本中的全局级别使用以下代码:

expr = 2 z;
f[z_] = expr;
f[7]
(*output: 14*)
Run Code Online (Sandbox Code Playgroud)

但是当我将相同的代码块放入模块并使expr本地时,它会产生不同的输出.

Clear[f];
Module[{expr},
 expr = 2 z;
 f[z_] = expr;
 f[7]]
(*output: 2z*)
Run Code Online (Sandbox Code Playgroud)

如果跟踪上面的模块调用,则会发现Set [f [z_],expr]被重写为Set [f [z $ _,expr].现在这个z-> z $转换发生在Set的lhs和rhs上.然而,它在expr被评估之前发生,这导致在全局级别获得不同的结果.

只有当rhs具有Module调用的本地符号时,才会发生转换z-> z $.

为什么Mathematica选择在模块调用中更改此语法?做出这个决定的是什么语言/实现设计权衡.

programming-languages wolfram-mathematica

7
推荐指数
2
解决办法
924
查看次数

如何处理"恐慌:不可能发生"并继续在Haskell

我有以下代码使用GHC API加载模块并获取表达式的类型:

typeObjects :: [String] -> [String] -> IO [Type]
typeObjects modules objects = do
  defaultErrorHandler defaultDynFlags $ do
    runGhc (Just libdir) $ do
      dflags <- getSessionDynFlags
      setSessionDynFlags dflags
      targets <- mapM ((flip guessTarget) Nothing) modules
      setTargets targets
      result <- load LoadAllTargets
      case result of
          Failed -> error "Compilation failed"
          Succeeded -> do
            m <- mapM (((flip findModule) Nothing) . mkModuleName) modules
            setContext m []
            values <- mapM exprType objects
            return values
Run Code Online (Sandbox Code Playgroud)

如果表达式没有进行类型检查,则整个程序崩溃:

TestDynamicLoad: panic! (the 'impossible' happened)
   (GHC version …
Run Code Online (Sandbox Code Playgroud)

haskell typechecking dynamic-loading ghc-api

7
推荐指数
1
解决办法
1829
查看次数

分离数据加载/卸载和处理逻辑

有时需要执行一些复杂的例程来检索或保存正在处理的数据.在这种情况下,人们想要分离数据生成和数据处理逻辑.常见的方法是使用类似iteratee的功能.有很多不错的图书馆:管道,管道等.在大多数情况下,他们会做这件事.但是AFAIK它们(除了,可能是管道)受到处理顺序的限制.

但考虑一个日志查看器示例:人类可能希望随机来回漫步.他也可以放大和缩小.我担心迭代者在这里无能为力.

一个简单的解决方案可能如下所示:

-- True is for 'right', 'up', etc. and vice versa 
type Direction = Bool

class Frame (f :: * -> *) where
  type Dimension f :: *

  type Origin f :: * -> *

  grow', shrink' move' :: Monad m => Dimension f -> Direction -> f a -> m (f a)

  move' dim dir f = grow' dim dir f >>= shrink' dim (not dir)

  liftF' :: (Origin f a -> b) -> f a -> …
Run Code Online (Sandbox Code Playgroud)

haskell haskell-pipes

7
推荐指数
1
解决办法
187
查看次数

增量宏定义是否可行?

我经常发现以下类型的增量定义很有用:

(define (foo) (display "bar"))
(foo)
;prints bar
(define foo (let ((bar foo))
              (lambda ()
                (display "foo")
                (bar))))

(foo)
;prints foobar
Run Code Online (Sandbox Code Playgroud)

如何使用宏预先形成此类增量定义?我无法让let-syntax提供相同的功能.

目前我使用plt方案,但也希望在不同的lisp实现中看到答案.

编辑:

天真的我想做以下事情:

(define-syntax foo
  (syntax-rules ()
    ((_) (display "bar"))))

(define-syntax foo
  (let-syntax ((old-foo (syntax-rules () ((_) (foo)))))
    (syntax-rules ()
      ((_) (begin
             (display "foo")
             (old-foo))))))
Run Code Online (Sandbox Code Playgroud)

将朴素宏翻译为工作plt方案宏:

(require-for-syntax scheme/base) 
(define-syntax foo
  (syntax-rules ()
    [(foo) (display "bar")]))
(define-syntax foo
  (let ([old (syntax-local-value #'foo)])
    (lambda (stx)
      #`(begin #,((syntax-rules ()
               [(_) (begin (display "foo"))]) stx)
             #,(old #'(_))))))
(foo)
Run Code Online (Sandbox Code Playgroud)

如果我错过了一个更好的方法让我知道.

lisp macros scheme

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

管道中的"子解析器" - attoparsec

我正在尝试使用Haskell中的pipes-attoparsec解析二进制数据.管道(代理)涉及的原因是将读取与解析交错以避免大文件的高内存使用.许多二进制格式基于块(或块),它们的大小通常由文件中的字段描述.我不确定这个块的解析器是什么被调用,但这就是我所说的标题中的"sub-parser".我遇到的问题是以简洁的方式实现它们而没有可能很大的内存占用.我想出了两个在某些方面都失败的替代方案.

备选方案1是将块读入单独的字节串并为其启动单独的解析器.简洁,大块将导致高内存使用.

备选方案2是在相同的上下文中保持解析并跟踪消耗的字节数.这种跟踪容易出错,并且似乎会影响组成最终blockParser的所有解析器.对于格式错误的输入文件,在比较跟踪大小之前,还可以通过进一步解析比大小字段所指示的方式来浪费时间.

import Control.Proxy.Attoparsec
import Control.Proxy.Trans.Either
import Data.Attoparsec as P
import Data.Attoparsec.Binary
import qualified Data.ByteString as BS

parser = do
    size <- fromIntegral <$> anyWord32le

    -- alternative 1 (ignore the Either for simplicity):
    Right result <- parseOnly blockParser <$> P.take size
    return result

    -- alternative 2
    (result, trackedSize) <- blockparser
    when (size /= trackedSize) $ fail "size mismatch"
    return result

blockParser = undefined

main = withBinaryFile "bin" ReadMode go where
    go h = fmap print . runProxy . runEitherK …
Run Code Online (Sandbox Code Playgroud)

parsing haskell attoparsec haskell-pipes

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

用管道的WriterP编写一个简单的累加器

使用管道库,我想编写一个程序来从某个源读取数据并单独累积它(比如说Sum).最简单的方法是,

 import Control.Proxy as 
 import Data.Monoid (Sum)

 main = do
     let source = enumFromToS (0::Int) 5
     a <- runWriterT $ runProxy $ source >-> foldD Sum
     print a
Run Code Online (Sandbox Code Playgroud)

当然,虽然这适用于小型源,但由于WriterT累加器的惰性,大输入会导致可怕的堆栈溢出.

值得庆幸的是,它似乎pipes预料到了这一点,提供了一个WriterP带有严格累加器的代理.不幸的是,围绕这个代理的文档非常稀少.经过一番探索(并简化问题而不是为每个下游元素累积1),我来到这个程序,

import Control.Proxy
import Control.Proxy.Trans.Writer
import Data.Monoid (Sum)

main = do
    let source = enumFromToS (0::Int) 5
    a <- runProxy $ runWriterK $ source >-> \x->tell (Sum 1::Sum Int)
    print a
Run Code Online (Sandbox Code Playgroud)

当然,这个程序甚至没有正确地执行简化的任务,因为它累积到1而不是6.如果我没有弄错,这个行为可以解释为管道在终止之前只读取一个元素.要重复直到输入结束,我想出了以下内容,

import Control.Proxy
import Control.Proxy.Trans.Writer
import Data.Monoid (Sum)

main = do
    let …
Run Code Online (Sandbox Code Playgroud)

haskell haskell-pipes

4
推荐指数
1
解决办法
537
查看次数

在基本monad中将代理与不同的EitherT组合在一起

例如,有......

consumer :: Proxy p => () -> Consumer p a (EitherT String IO) ()
producer :: Proxy p => () -> Producer p a (EitherT ByteString IO) r
Run Code Online (Sandbox Code Playgroud)

......我该如何工作?

session :: EitherT ByteString (EitherT String IO) ()
session = runProxy $ producer >-> consumer
Run Code Online (Sandbox Code Playgroud)

:我读过混合基地单子Control.Proxy.Tutorial.我得到了第一个例子,但无法理解人为的例子.更多的例子,不是那么明显但不那么做作,可能会澄清如何使用hoistlift匹配任何基础monad的组合.

haskell proxies haskell-pipes

4
推荐指数
3
解决办法
479
查看次数