小编cro*_*eea的帖子

一种避免常见使用unsafePerformIO的方法

我经常在Haskell代码中找到这种模式:

options :: MVar OptionRecord
options = unsafePerformIO $ newEmptyMVar

...

doSomething :: Foo -> Bar
doSomething = unsafePerformIO $ do
  opt <- readMVar options
  doSomething' where ...
Run Code Online (Sandbox Code Playgroud)

基本上,一个人有一个选项或类似的记录,最初是在程序开始时设置的.由于程序员很懒惰,他不想options在整个程序中携带记录.他定义了一个MVar保持它 - 由丑陋的使用定义unsafePerformIO.程序员确保状态只设置一次,并且在任何操作发生之前.现在程序的每个部分都必须unsafePerformIO再次使用,只是为了提取选项.

在我看来,这样的变量被认为是实用的纯粹(不要打败我).是否有一个库抽象出这个概念,并确保变量只设置一次,即在初始化之前没有调用,并且不需要写unsafeFireZeMissilesAndMakeYourCodeUglyAnd DisgustingBecauseOfThisLongFunctionName

haskell global-variables purely-functional unsafe-perform-io

16
推荐指数
3
解决办法
2375
查看次数

Haskell反思中的黑魔法

我希望有人可以对Data.Reflection中的黑魔法有所了解.相关片段是:

{-# LANGUAGE CPP #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE KindSignatures #-}

module Data.Reflection
    (
      Reifies(..)
    , reify
    ) where

import Data.Proxy
import Unsafe.Coerce

class Reifies s a | s -> a where
  -- | Recover a value inside a 'reify' context, given a proxy for its
  -- reified type.
  reflect :: proxy s -> a

newtype Magic a r = Magic (forall …
Run Code Online (Sandbox Code Playgroud)

reflection haskell

16
推荐指数
1
解决办法
2536
查看次数

修复3'性能和正确使用'现在'

这里有一个基本的monad问题,与Repa无关,还有几个与Repa有关的问题.

我正在使用Repa3工作.我无法获得高效的并行代码.如果我让我的函数返回延迟数组,我会得到极其缓慢的代码,可以很好地扩展到8个内核.该代码每GHC探测器占用超过20GB的内存,并且比基本的Haskell未装箱矢量运行几个数量级.

或者,如果我让所有函数返回Unboxed清单数组(仍然尝试在函数中使用fusion,例如当我执行'map')时,我获得了更快的代码(仍然比使用Haskell未装箱的向量慢)根本没有扩展,实际上随着核心数量的增加会略微变慢.

基于Repa-Algorithms中的FFT示例代码,似乎正确的方法是始终返回清单数组.有没有我应该返回延迟数组的情况?

FFT代码也充分利用了'now'功能.但是,当我尝试在我的代码中使用它时,我收到类型错误:

type Arr t r = Array t DIM1 r
data CycRingRepa m r = CRTBasis (Arr U r)
                     | PowBasis (Arr U r)

fromArray :: forall m r t. (BaseRing m r, Unbox r, Repr t r) => Arr t r -> CycRingRepa m r
fromArray = 
    let mval = reflectNum (Proxy::Proxy m)
    in \x ->
        let sh:.n = extent x
        in assert (mval == 2*n) PowBasis $ now $ computeUnboxedP $ bitrev x
Run Code Online (Sandbox Code Playgroud)

没有'now',代码编译得很好.使用'now',我收到以下错误: …

monads performance profiling haskell repa

15
推荐指数
2
解决办法
1143
查看次数

让重命名函数中断代码

在将代码迭代到正确的版本时,我遇到了以下好奇心:

{-# LANGUAGE RankNTypes #-}

module Foo where

import Data.Vector.Generic.Mutable as M
import Control.Monad.Primitive

-- an in-place vector function with dimension
data DimFun v m r = 
  DimFun Int (v (PrimState m) r -> m ())

eval :: (PrimMonad m, MVector v r) => DimFun v m r -> v (PrimState m) r -> m ()
eval = error ""

iterateFunc :: (PrimMonad m, MVector v r)
            => (forall v' . (MVector v' r) => DimFun v' m r) -> …
Run Code Online (Sandbox Code Playgroud)

haskell ghc

15
推荐指数
2
解决办法
459
查看次数

秩-2类型的模式匹配

我试图理解为什么这个代码的一个版本编译,而一个版本没有.

{-# LANGUAGE RankNTypes, FlexibleContexts #-}

module Foo where

import Data.Vector.Generic.Mutable as M
import Data.Vector.Generic as V
import Control.Monad.ST
import Control.Monad.Primitive

data DimFun v m r = 
  DimFun {dim::Int, func :: v (PrimState m) r -> m ()}

runFun1 :: (Vector v r, MVector (Mutable v) r) => 
  (forall m . (PrimMonad m) => DimFun (Mutable v) m r) -> v r -> v r
runFun1 (DimFun dim t) x | V.length x == dim = runST $ do
  y …
Run Code Online (Sandbox Code Playgroud)

haskell ghc

15
推荐指数
1
解决办法
871
查看次数

将Dict转变为约束

我有一个类Cyc c r,它具有表单数据的功能c m r,其中m是一个幻像类型.例如,

class Cyc c r where
  cyc :: (Foo m, Foo m') => c m r -> c m' r
Run Code Online (Sandbox Code Playgroud)

我没有做出m类参数的充分理由.出于此示例的目的,主要原因是它减少了对函数的约束数量.在我的实际例子中,对这个界面更迫切的需求是我使用更改和隐藏的幻像类型,所以这个界面让我得到Cyc任何幻像类型的约束.

这个选择的一个缺点是我不能制作Num (c m r)超类约束Cyc.我的意图是c m r应该Num随时随地(Cyc c r, Foo m).目前的解决方案非常烦人:我在课堂上添加了方法Cyc

witNum :: (Foo m) => c m r -> Dict (Num (c m r))
Run Code Online (Sandbox Code Playgroud)

哪种方式完成同样的事情.现在,当我有一个带有泛型Cyc并需要Num (c m r)约束的函数时,我可以写:

foo :: …
Run Code Online (Sandbox Code Playgroud)

haskell ghc

15
推荐指数
1
解决办法
249
查看次数

使用向量的样式与性能

这是代码:

{-# LANGUAGE FlexibleContexts #-}

import Data.Int
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Generic as V

{-# NOINLINE f #-} -- Note the 'NO'
--f :: (Num r, V.Vector v r) => v r -> v r -> v r
--f :: (V.Vector v Int64) => v Int64 -> v Int64 -> v Int64
--f :: (U.Unbox r, Num r) => U.Vector r -> U.Vector r -> U.Vector r
f :: U.Vector Int64 -> U.Vector Int64 -> U.Vector Int64 …
Run Code Online (Sandbox Code Playgroud)

lambda haskell pointfree

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

在GHCi中键入Family Shenanigans

这是我的代码:

{-# LANGUAGE TypeFamilies, TypeOperators, DataKinds, PolyKinds, FlexibleContexts, UndecidableInstances #-}

module Foo where

import Data.Singletons.Prelude
import Data.Type.Equality

data TP a b

-- foldl (\(bool, r) x -> (bool && (r == x), r)) (True, head xs) xs
type family Same (b :: Bool) (r :: k) (rq :: [k]) :: k where
  Same bool r (x ': xs) = Same (bool :&& (r == x)) r xs
  Same bool r '[] = TP bool r

data NotEqualFailure
-- converts a …
Run Code Online (Sandbox Code Playgroud)

haskell ghc

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

monad内部的多态性

我试图拉值超出一个单子,但保留,它不依赖于单子,多态.特别:

foo :: (Monad mon, Ring a) => mon a
foo = return 3

main :: IO ()
main = do
  x <- foo
  print (x :: Double)
  print (x :: Int)
Run Code Online (Sandbox Code Playgroud)

关键是计算的monadic部分计算起来很昂贵,所以我只想做一次,同时保持monad多态的值.到目前为止我的所有尝试:

  1. x签名forall a. (Ring a) => a)
  2. foo :: (Monad mon) => mon (forall a . (Ring a) => a)
  3. 启用-XNoMonomorphismRestrictionNoMonoLocalBins

对于不能使用的impregicative polymorphism,或者没有工作或给出错误.是否有某种方法可以在没有不可预测的多态性的情况下从monad中提取多态值(或者:在GHC中是否有一种安全的方法来使用impredicative polymorphism)?

haskell ghc

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

静态链接C++库和Haskell库

设置:我有一个Haskell库HLib,可以调用C/C++后端CLib来提高效率.后端很小,专门用于HLib.的接口CLib被通过暴露HLib; HLib测试,HLib基准测试和第三方库依赖于HLib不会直接进行FFI调用CLib.从测试/基准/第三方lib的角度来看,HLib应该是纯粹的Haskell.这意味着在,例如小集团文件部分,HLib测试,应该有任何引用-lCLib,libCLib等等,只有build-dependsHLib,并且可执行文件不应该需要寻找一个动态CLib库.我需要能够构建和运行HLib第三方库中的所有可执行文件,以及运行cabal repl开发.

最初,CLib写于纯C.卡瓦尔具有用于这种情况下的支持,并且我可以集成CLibHLib在精确地,通过使用上面描述的方式include-dirs,c-sourcesincludes在小集团文件字段.

CLib已经发展成为一个C++库,我无法弄清楚如何让cabal轻松集成.相反,我使用自定义构建和Setup.hs的makefile,就像这样.你可以在这里看到这个方法的一个小例子1,2.

在那个例子中,我无法运行cabal repl,HLib因为"加载档案不受支持".这实际上意味着我需要一个动态C++库,它很容易创建(在CLibmakefile中有一个注释行来完成它).但是,如果我确实创建了动态C++库,那么HLib由于"没有这样的文件或目录libclib.so" ,测试会在运行时失败.这很糟糕(除了崩溃),因为测试可执行文件链接到动态库,这不是我想要的.

具体来说,测试HLibSimpleLib应该通过,我应该能够cabal repl在 …

haskell ghc cabal

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