小编Pau*_*son的帖子

在Haskell中证明"没有腐败"

我在安全关键行业工作,我们的软件项目通常都有安全要求; 我们必须证明该软件具有高度确定性.通常这些都是消极的,例如"不应该比1更频繁地腐败".(我应补充一点,这些要求来自统计系统安全要求).

腐败的一个来源显然是编码错误,我想使用Haskell类型系统来排除这些错误中的至少一些类.像这样的东西:

首先,这是我们的关键数据项,不能被破坏.

newtype Critical = Critical String
Run Code Online (Sandbox Code Playgroud)

现在我想将这个项目存储在其他一些结构中.

data Foo = Foo Integer Critical
data Bar = Bar String Critical
Run Code Online (Sandbox Code Playgroud)

现在我想编写一个从Foo到Bar的转换函数,保证不会弄乱关键数据.

goodConvert, badConvert :: Foo -> Bar

goodConvert (Foo n c) = Bar (show n) c

badConvert (Foo n (Critical s)) = Bar (show n) (Critical $ "Bzzt - " ++ s)
Run Code Online (Sandbox Code Playgroud)

我希望"goodConvert"键入check,但"badConvert"键入失败类型检查.

显然,我可以小心地不将Critical构造函数导入到进行转换的模块中.但是如果我能在类型中表达这个属性会好得多,因为那时我可以编写保证保留这个属性的函数.

我尝试在各个地方添加幻像类型和"forall",但这没有用.

可行的一件事是不导出Critical构造函数,然后具有

mkCritical :: String -> IO Critical
Run Code Online (Sandbox Code Playgroud)

由于创建这些关键数据项的唯一位置是在输入函数中,这是有道理的.但我更喜欢更优雅和通用的解决方案.

编辑

在评论中,FUZxxl建议看一下Safe Haskell.这看起来是最好的解决方案.而不是像我原来想要的那样在类型级别添加"无损坏"修饰符,看起来你可以在模块级别执行它,如下所示:

1:创建一个模块"Critical",导出Critical数据类型的所有功能,包括其构造函数.通过在标题中添加"{ - #LANGUAGE Unsafe# - }"将此模块标记为"不安全".

2:创建一个"SafeCritical"模块,重新导出除构造函数和可能用于破坏临界值的任何其他函数之外的所有内容.将此模块标记为"值得信赖".

3:将处理临界值所需的任何模块标记为"安全"而不会损坏.然后使用它来演示导入为"safe"的任何函数都不会导致损坏到Critical值.

这将留下较少的代码,例如解析关键值的输入代码,需要进一步验证.我们无法消除此代码,但减少需要详细验证的数量仍然是一个重大的胜利.

该方法基于以下事实:除非函数返回,否则函数不能创建新值.如果一个函数只获得一个临界值(如上面的"转换"函数),那么它就是唯一可以返回的值. …

haskell

27
推荐指数
2
解决办法
1199
查看次数

表示连续概率分布

我有一个涉及连续概率分布函数集合的问题,其中大多数是根据经验确定的(例如出发时间,运输时间).我需要的是一些方法来获取这些PDF中的两个并对它们进行算术运算.例如,如果我有两个值x取自PDF X,而y取自PDF Y,我需要得到(x + y)的PDF或任何其他操作f(x,y).

分析解决方案是不可能的,所以我正在寻找的是允许这些事情的PDF的一些表示.一个明显的(但计算上很昂贵的)解决方案是monte-carlo:生成大量的x和y值,然后测量f(x,y).但这需要太多的CPU时间.

我确实考虑将PDF表示为范围列表,其中每个范围具有大致相等的概率,有效地将PDF表示为统一分布列表的并集.但我看不出如何将它们结合起来.

有没有人对这个问题有任何好的解决方案?

编辑:目标是创建一种用于处理PDF的迷你语言(又称域特定语言).但首先我需要理清基础表示和算法.

编辑2: dmckee建议直方图实现.这就是我对统一分布列表的看法.但我不知道如何将它们组合起来创建新的发行版.最终我需要找到像P(x <y)这样的东西,这可能是非常小的.

编辑3:我有一堆直方图.它们不是均匀分布的,因为我是根据出现数据生成的,所以基本上如果我有100个样本并且我想在直方图中有10个点,那么我会为每个条形分配10个样本,并使条形变宽但是恒定区域.

我已经想出要添加PDF,你就可以对它们进行卷积,而且我已经为这个数学做了数学鉴定.当您对两个均匀分布进行卷积时,您会得到一个包含三个部分的新分布:更宽的均匀分布仍然存在,但是每边都有一个三角形,较窄的宽度.因此,如果我对X和Y的每个元素进行卷积,我会得到一堆这些,都是重叠的.现在我想弄清楚如何将它们全部相加,然后得到一个最佳近似直方图.

我开始怀疑蒙特卡洛毕竟不是一个坏主意.

编辑4: 本文详细讨论了均匀分布的卷积.一般来说,你得到一个"梯形"分布.由于直方图中的每个"列"是均匀分布,我曾希望通过卷积这些列并对结果求和来解决问题.

然而,结果比输入复杂得多,并且还包括三角形. 编辑5: [错误的东西删除].但是如果这些梯形近似于具有相同面积的矩形,那么你得到正确答案,并且减少结果中矩形的数量看起来也非常简单.这可能是我一直试图找到的解决方案.

编辑6:解决了!以下是此问题的最终Haskell代码:

-- | Continuous distributions of scalars are represented as a
-- | histogram where each bar has approximately constant area but
-- | variable width and height.  A histogram with N bars is stored as
-- | a list of N+1 values.
data Continuous = C {
      cN :: Int,
      -- ^ Number of bars …
Run Code Online (Sandbox Code Playgroud)

algorithm math statistics haskell probability

22
推荐指数
3
解决办法
3146
查看次数

在Scratch之后教什么?

我的儿子在Scratch中热情地编写简单的游戏.然而,Scratch是一个非常简单的编程环境(甚至没有子程序),我很快就会看到他需要转向别的东西.

有没有人知道一种很好的学习语言,它使图形变得简单但提供了"真正的"编程功能,如数据结构,函数,数组和列表?

如果它在Linux(Ubuntu)下运行,则奖励积分."foo with library Bar"形式的答案也是一种选择.

language-agnostic mit-scratch block-programming

21
推荐指数
5
解决办法
3009
查看次数

在QuickCheck中缩小记录的惯用法

假设我有一个记录类型:

data Foo = Foo {x, y, z :: Integer}
Run Code Online (Sandbox Code Playgroud)

编写Arbitrary实例的一种巧妙方法是使用Control.Applicative,如下所示:

instance Arbitrary Foo where
   arbitrary = Foo <$> arbitrary <*> arbitrary <*> arbitrary
   shrink f = Foo <$> shrink (x f) <*> shrink (y f) <*> shrink (z f)
Run Code Online (Sandbox Code Playgroud)

因此,Foo的收缩列表是其成员所有收缩的笛卡尔积.

但是如果其中一个收缩返回[]那么整个Foo就不会收缩.所以这不起作用.

我可以尝试通过在缩小列表中包含原始值来保存它:

   shrink f = Foo <$> ((x f) : shrink (x f)) <*> ... {and so on}.
Run Code Online (Sandbox Code Playgroud)

但现在缩小(Foo 0 0 0)将返回[Foo 0 0 0],这意味着收缩将永远不会终止.所以这也不起作用.

看起来在这里应该使用<*>以外的其他东西,但我看不出是什么.

haskell quickcheck

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

为什么这会导致Haskell Conduit库中的内存泄漏?

我有一个管道管道处理一个长文件.我想每1000条记录为用户打印一份进度报告,所以我写了这样的:

-- | Every n records, perform the IO action.
-- Used for progress reports to the user.
progress :: (MonadIO m) => Int -> (Int -> i -> IO ()) -> Conduit i m i
progress n act = skipN n 1
   where
      skipN c t = do
         mv <- await
         case mv of
            Nothing -> return ()
            Just v ->
               if c <= 1
                  then do
                     liftIO $ act t v
                     yield v
                     skipN n (succ …
Run Code Online (Sandbox Code Playgroud)

haskell memory-leaks conduit

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

在Gtk2hs中渲染Cairo更新的正确方法是什么?

我正在编写一个具有单击并拖动功能的Haskell程序,因此每次鼠标移动事件都会向窗口绘制更新.目前我正在使用

renderWithDrawable myCanvas update
Run Code Online (Sandbox Code Playgroud)

然而,这很多都是闪烁的.我的理解是我需要创建一个单独的drawable(一个"表面"?),渲染到它,然后在一次操作中将它blit到屏幕窗口.但是我对这种方法的正确方法感到困惑.

我发现drawWindowBeginPaintRegion,它谈到消除闪烁.但是根据Haddock文档,它在Gtk3中删除了.所以我不确定我是否应该使用它,因为它似乎已被弃用.

我也在renderWithSimilarSurface开罗找到了,它似乎做了类似的事情.

我也不确定这些函数是如何关联的renderWithDrawable:我是否必须在函数内部使用它们,或者什么?

这样做的正确方法是什么?

编辑

这在开罗似乎是一个众所周知的事情.我正在试图弄清楚如何在Haskell中处理这个问题.

haskell gtk2hs cairo

10
推荐指数
1
解决办法
312
查看次数

使用gi-gtk和Reactive Banana捕获Haskell异常

当然,我的应用程序没有错误,但是如果它包含任何底部值,我想放入一个通用异常捕获器,它至少会弹出一个消息框告诉用户要报告什么类型的错误.因为我正在使用gi-gtk,我认为初始化后的任何异常都会从Gtk.main函数内部发生,所以我的main函数的结尾看起来像这样:

let executeProgram =
     catch Gtk.main $ \e -> do
           reportThisBugDialog $ show (e :: SomeException)
           -- Code here to try to recover to a known good state
           executeProgram
executeProgram
Run Code Online (Sandbox Code Playgroud)

我也使用Reactive Banana以防相关,但这不在FRP代码中.

但是,这不会捕获任何异常.我输入error "Test Exception"了"Help About"的处理程序,我的程序刚退出并在控制台上打印了一条消息(我的用户当然不会看到).

当我对代码响应GTK信号时,如何捕获代码中发生的异常?

haskell frp gtk3

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

如何将图库与GTK drawables一起使用?

我正在尝试学习如何使用图表库和Cairo/GTK后端绘制图表.我有一个空白的窗口出现,但我的绘图不会呈现.我究竟做错了什么?

module Main where

import Control.Monad.Trans (liftIO)
import Graphics.UI.Gtk
import Diagrams.Backend.Cairo
import Diagrams.Backend.Cairo.Gtk
import Diagrams.Prelude

main :: IO ()
main = do
  initGUI
  window <- windowNew
  canvas <- drawingAreaNew
  canvas `on` sizeRequest $ return (Requisition 1000 1000)
  set window [ containerBorderWidth := 10,
               containerChild := canvas ]
  canvas `on` exposeEvent $ renderFigure
  onDestroy window mainQuit
  widgetShowAll window
  mainGUI


renderFigure :: EventM EExpose Bool
renderFigure = do
   win <- eventWindow
   liftIO $ renderToGtk win $ toGtkCoords figure
   -- liftIO …
Run Code Online (Sandbox Code Playgroud)

gtk haskell haskell-diagrams

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

用于图形模型编辑器的拉链数据结构

我正在为"模型"编写一个图形编辑器(即带有某种语义的框和行的集合,例如UML,其细节在这里无关紧要).所以我希望有一个表示模型的数据结构,以及一个图表,其中对图表的编辑会导致模型中的相应更改.因此,例如,如果模型元素在属性中有一些文本,并且我编辑图中的文本,我希望更新模型元素.

该模型可能会表示为树,但我希望图表编辑器尽可能少地了解模型表示.(我正在使用图表框架,因此将任意信息与图形元素相关联很容易).如果我能弄清楚应该是什么,可能会有一个"模型"类来编码接口.

如果我用命令式语言执行此操作,那将很简单:我只需要从图中的图形元素返回到模型元素.从理论上讲,我仍然可以通过从大量的IORef集合中构建模型来实现这一点,但那将是在Haskell中编写Java程序.

显然,每个图形元素都会有一些与之关联的cookie,这样就可以实现模型更新.一个简单的答案是为每个模型元素提供唯一标识符,并将模型存储在Data.Map查找表中.但这需要大量的簿记才能确保没有两个模型元素获得相同的标识符.这也是一种"串型"解决方案; 你必须处理一个对象被删除的情况,但是在其他地方有一个悬挂的引用,并且很难对你的类型中的模型的内部结构说些什么.

另一方面,奥列格的关于具有多个孔和光标的拉链以及清晰的交易共享的着作听起来像是一个更好的选择,只要我能理解它.我得到了列表和树拉链的基本概念以及数据结构的区别.图表中的每个元素都可以将光标保存到模型的拉链中吗?那么如果进行了更改,则可以将其提交给所有其他游标?包括树操作(例如将子树从一个地方移动到另一个地方)?

如果有一些关于分隔延续的教程,以及它们如何使Oleg的多光标拉链工作,这比Oleg的帖子稍微陡峭一点,那对我来说尤其有帮助吗?

haskell zipper data-structures

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

如何为和型编写镜头

我有这样的类型:

data Problem =
   ProblemFoo Foo |
   ProblemBar Bar |
   ProblemBaz Baz
Run Code Online (Sandbox Code Playgroud)

Foo,BarBaz都对他们的名字一个镜头:

fooName :: Lens' Foo String
barName :: Lens' Bar String
bazName :: Lens' Baz String
Run Code Online (Sandbox Code Playgroud)

现在我想制作一个镜头

problemName :: Lens' Problem String
Run Code Online (Sandbox Code Playgroud)

很明显,我可以使用lens构造函数和一对case语句来编写它,但是有更好的方法吗?

对于文档outside关于使用棱镜作为一种一流的格局,这听起来暗示,但我看不出如何真正做到这一点的会谈.

(编辑:添加Baz案例,因为我的真正问题不是同构的Either.)

haskell haskell-lens

7
推荐指数
3
解决办法
207
查看次数