小编Mat*_*hid的帖子

Parsec:消耗所有输入

我对Parsec的一个常见问题是,如果它出现在"正确"的位置,它往往会忽略无效输入.

作为一个具体的例子,假设我们有integer :: Parser Int,我写

expression = sepBy integer (char '+')
Run Code Online (Sandbox Code Playgroud)

(暂时忽略空白问题.)

这正确解析类似"123 + 456 + 789"的内容.但是,如果我喂它"123 + 456-789",它会愉快地忽略非法的" - "字符和表达式的尾部; 我实际上想要一条错误消息告诉我有关无效输入的信息,而不仅仅是让它无声地忽略该部分.

我明白为什么会这样; 我不确定的是如何解决它.设计使用所有提供的输入的解析器的一般方法是什么?只有当所有输入都是有效表达式时才能成功?

haskell parsec

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

类型安全的printf

标准库提供了一个printf功能,可以成为varadic.然而,它没有做的是编译时检查参数类型是否与格式字符串匹配.这需要依赖类型,听起来真的很难实现!(你必须使用类型签名来解析整个格式字符串...哎呀!)

但经过反思,现在我想知道......我们可以用模板Haskell做到这一点吗?事实上,有没有人为此写过一个库?

(看起来你可以很容易地编写一个准引脚来读取printf格式规范并生成必要的N-arg函数......)

string haskell types

13
推荐指数
2
解决办法
750
查看次数

Haskell:检测当前的操作系统

我正在编写一个Haskell包.我希望它在Windows和Unix上表现不同.什么是最"正确"的方法来检测正在编译我的代码的OS?

我确实尝试过使用CPP #ifdef _WIN32,但这似乎根本不起作用.

还有另一个宏吗?我可以让Cabal告诉我吗?我需要完全尝试别的吗?

haskell

13
推荐指数
4
解决办法
2001
查看次数

未使用的let绑定在Haskell中是否有任何影响?

我刚才意识到写这个是合法的:

let _ = sum [1..100]
in  "Hello"
Run Code Online (Sandbox Code Playgroud)

let-binding似乎绝对没有任何作用.

但现在我想知道这里的确切语义.可以编写一个包含_绑定的程序,但删除该绑定会明显改变所述程序的含义吗?

基本上,我想知道自动删除这样的绑定是否安全.据我所知,这种绑定的价值不可能影响任何事情.然而,似乎假设它的类型可能会影响其他东西.任何人都可以构建一个例子吗?

syntax haskell

13
推荐指数
2
解决办法
521
查看次数

找到功能X最早的包版本

所以我坐在这里想知道为什么我找不到我正在寻找的功能,事实证明它在我安装的软件包版本中不存在.

那么我如何让Hackage告诉我该功能的添加版本是什么?

(特别是,我可以在我的Cabal描述中指定正确的包边界.)

haskell cabal hackage

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

如何测试GHC插件?

GHC的最新版本具有新的“插件”功能,您可以在其中编写普通的Haskell代码,像往常一样对其进行编译,然后将其插入到编译器中,以使其能够处理GHC的内部状态。

这是非常酷。但是,有一个小障碍:要执行此操作,必须已编译插件(似乎很明显)并将其注册为软件包DB中的软件包!

插件完成后就可以了;将其打包并放在Hackage上,以供所有人欣赏。但是,在尝试开发软件包时如何解决呢?在每次编辑时,您都必须手动注销旧软件包,构建新软件包并进行注册,您的edit-compile-execute周期如何工作?

基本上,在尝试开发插件时,有什么方法可以避开此要求?

haskell ghc

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

我的程序Turing-complete?

我花了一两个星期编写一个简单的逻辑解算器.构建它之后,我发现自己想知道它所解决的语言是否是图灵完备的.因此,我编写了一小组方程式,它们接受SKI组合子演算中的任何有效表达式,并生成包含该表达式的正常形式的结果集.由于SKI Turing-complete,证明我的语言可以执行SKI将证明其图灵完整性.

然而,有一个小故障.解算器不会按正常顺序减少表达式.实际上它的作用是尝试每一个可能的减少订单.这意味着解决方案集通常很大.如果存在正常形式,它将存在于某处,但很难分辨到哪里.

这让我有两个问题:

  • 我的语言图灵完整吗?或者我需要找到更好的证据吗?

  • 解决方案的数量是输入的可计算函数吗?

(起初我假设解决方案集的大小在输入大小中是指数或因子.但仔细观察,这不是真的.你可以编写已经处于正常形式的巨大表达式,以及不终止的小表达式我有一种感觉,确定解决方案集的大小可能等于解决停机问题,但我不完全确定......)

haskell turing-complete

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

控制并行执行

Haskell提供了一个par组合器,它将一个"火花"排队,以便与当前线程并行进行可能的评估.它还提供了一个pseq组合器,它强制评估纯代码以特定顺序发生.

Haskell似乎没有提供的是产生几个火花的方法,然后等待它们全部完成.使用显式并发实现这一点非常简单,但纯粹的火花似乎是不可能的.

在某种程度上,这可能是因为火花的预期用例.它们似乎是为投机评估而设计的.也就是说,做可能需要但可能不需要的工作.因此,火花仅在核心上运行,否则它们是空闲的.

但是,这不是我的用例.我知道很多结果,事实上很快就会需要.如果我在火花爆发之前开始尝试处理结果,我将再次以一堆失败的火花结束单线程.

当然,par 等待火花完成,它不会达到任何并行性!但如果有某种方法可以产生几个火花然后等待它们全部完成,那将是非常有用的.我找不到任何方法可以做到这一点.

有没有人有任何有用的建议?(显然,除了"使用显式并发"之外).

parallel-processing haskell

12
推荐指数
2
解决办法
492
查看次数

正确设计Haskell异常处理

我目前正试图围绕在Haskell中使用异常的正确方法.例外如何运作是直截了当的; 我试图清楚地了解解释它们的正确方法.

基本的立场是,在设计良好的应用程序中,异常不应该逃到顶层.任何例外显然都是设计者没有预料到的例外 - 即程序错误(例如,除以零),而不是异常的运行时发生(例如,未找到文件).

为此,我编写了一个简单的顶级异常处理程序,它捕获所有异常并打印一条消息,stderr说"这是一个错误"(在重新抛出异常以终止程序之前).

但是,假设用户按下Ctrl + C. 这会导致抛出异常.显然,这不是任何程序错误.但是,如果没有预料到并且对此用户中止做出反应可能会被视为错误.所以也许程序应该抓住它并适当地处理它,在退出之前做任何必要的清理.

但问题是......处理此问题的代码将捕获异常,释放任何资源或其他内容,然后重新抛出异常!因此,如果异常使其达到顶级,那并不一定意味着它未被处理.这只是意味着我们想要快速退出.

所以,我的问题:是否应该以这种方式将异常用于流量控制?是否每个明确捕获的函数都UserInterrupt使用显式流控制结构来手动退出而不是重新抛出异常?(但那么来电者如何知道也退出?)是否可以UserInterrupt达到顶级?但在那种情况下,ThreadKilled同样的论点也可以吗?

简而言之,中断处理程序应该为UserInterrupt(并且可能ThreadKilled)做出特殊情况吗?怎么样?HeapOverflow或者StackOverflow?是一个错误吗?或者是"超出计划控制范围的情况"?

haskell exception-handling

12
推荐指数
2
解决办法
891
查看次数

与无类型lambda演算的冒险

我们偶尔会有人询问在Haskell中实现无类型的lambda演算.[当然,我现在找不到任何这些问题,但我确定我已经看过了!]只是为了咯咯笑,我以为我会花一些时间玩这个.

做一些像这样的事情是微不足道的

i = \ x -> x
k = \ x y -> x
s = \ f g x -> (f x) (g x)
Run Code Online (Sandbox Code Playgroud)

这非常有效.但是,只要你尝试做类似的事情

s i i
Run Code Online (Sandbox Code Playgroud)

类型检查员正确地抱怨无限类型.基本上,无类型lambda演算中的所有东西都是一个函数 - 这实际上意味着所有函数都具有无限的特征.但是Haskell只允许有限度的函数.(因为,真的,为什么你想要无限的灵魂?)

好吧,事实证明我们可以很容易地采取这种限制:

data Term = T (Term -> Term)

T f ! x = f x

i = T $ \ x -> x
k = T $ \ x -> T $ \ y -> x
s = T $ \ …
Run Code Online (Sandbox Code Playgroud)

haskell types lambda-calculus

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