Haskell堆中以下值/表达式/函数的thunk是什么样的?
val = 5 -- is `val` a pointer to a box containing 5?
add x y = x + y
result = add 2 val
main = print $ result
Run Code Online (Sandbox Code Playgroud)
考虑到它的惰性评估模式,可以很好地了解这些在Haskell中的表示方式.
不太了解Haskell中并发性和并行性的上下文中的确定性.一些例子会有所帮助.谢谢
parallel-processing concurrency haskell deterministic non-deterministic
我的桌面上有ghc6和ghc7.要安装新软件包(对于特定的ghc版本),我使用cabal
标志--with-compiler=<ghc-dir>
来指定我想要安装软件包的ghc.
我cabal update
在安装任何新包之前做的.但是如何指定我想要更新哪个ghc?我的意思是,没有--with-compiler
标志cabal install
.我认为就像我ghc-pkg7
用于ghc7一样,会有cabal7
.除了cabal install
我知道它应用哪个ghc版本的命令之外,我不知道哪个ghc受其他cabal命令的影响.
此外,当我这样做时,ghc-pkg check
我发现一些包的问题,我不知道如何解决.
我真的很想知道 - 如果有人有 - 在同一台机器上使用多个ghc版本时的良好做法.例如,如何进行安装,更新等
F#List
提供cons
(::
)运算符以在列表的前面添加项.是否有功能为此做同样的事情Seq
?我遇到的唯一方法是使用Seq.append
如下.有没有更有效/更优雅的方式来做到这一点?
> let myLst = [1..5]
> 0::myLst;;
val it : int list = [0; 1; 2; 3; 4; 5]
> let mySeq = {1..5}
> Seq.append (seq [0]) mySeq;;
val it : seq<int> = seq [0; 1; 2; 3; ...]
Run Code Online (Sandbox Code Playgroud)
可能重复,但没有真正回答我的问题.
[1]Seq.append
如上所述使用
我正在使用Martin Erwig的功能图库(FGL)来表示以下简单的有向加权图.
genLNodes :: [LNode String]
genLNodes = zip [1..5] ["A","B","C","D","E"]
genLEdges :: [LEdge Int]
genLEdges = [(1,2,4),(1,3,1),(2,4,2),(3,4,2),(2,5,1),(4,5,1),
(2,1,4),(3,1,1),(4,2,2),(4,3,2),(5,2,1),(5,4,1)]
mygraph :: Gr String Int
mygraph = mkGraph genLNodes genLEdges
Run Code Online (Sandbox Code Playgroud)
现在我想找到一个节点到另一个节点如最短路径A
,以E
使用Dijkstra算法.似乎有一个功能可以做到Data.Graph.Inductive.Query.SP
:
dijkstra :: (Graph gr, Real b) => Heap b (LPath b) -> gr a b -> LRTree b
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何从提供的界面中使用它.任何帮助将非常感激.如果我以正确的方式创建有向加权图,或者是否还有其他(更好)的包,我还想听听其他任何建议吗?
我们可以使用类型同义词来表示函数,例如
type FuncDef = Int -> Int -> Int
Run Code Online (Sandbox Code Playgroud)
这避免了我们每次编写长函数定义.
使用:
someFunc :: FuncDef -> Int
Run Code Online (Sandbox Code Playgroud)
代替
someFunc :: (Int -> Int -> Int) -> Int
Run Code Online (Sandbox Code Playgroud)
这更易读,也更少代码.
简单的代数数据类型是直接的,易于进行模式匹配等,例如
data AType = X | Y | Z Int
matchType :: AType -> Bool
matchType X = ..
matchType Y = ..
matchType (Z _) = ..
Run Code Online (Sandbox Code Playgroud)
当我更多地了解Haskell数据类型时,我发现在定义新类型时我们可以在数据构造函数中使用函数定义.
data MyType a b = X | Y (a -> b)
Run Code Online (Sandbox Code Playgroud)
这让我感到困惑,并没有看到很多这方面的例子.在某种程度上,函数可以将另一个函数作为参数的高阶函数的想法与这种情况类似,除了它适用于数据类型.Haskell维基没有多说"高阶数据类型定义".我意识到我可能会把所有这些条款都弄错了,所以请纠正我,并指出我更多阅读.我真的希望看到具体用法.谢谢!
matchMyType :: (MyType a b) -> Bool
matchMyType X = ..
matchMyType …
Run Code Online (Sandbox Code Playgroud) 哪个列表,阵列或SEQ的是用于并行处理更高效,可以很容易地实现并行操作,例如parmap
,parfilter
等?
编辑:
感谢您的建议.Array.Parallel
看起来是个不错的选择.还检查了PSeq.fs
,我有一个关于如何pmap
工作的问题.
let pmap f xs =
seq { for x in xs -> async { return f xs } }
|> Async.Parallel
|> Async.RunSynchronously
Run Code Online (Sandbox Code Playgroud)
是否为序列中的每个元素生成了一个新线程?如果是这样,是否有办法将seq分解为块并为每个块创建一个新任务以进行并行评估?
我还想看看pmap
列表是否有类似的实现.我发现托马斯有一个ParallelList
在他的博客实施后这里.但我不确定将列表转换为数组以执行并行评估是否会产生过多的开销,是否可以避免?
编辑: 感谢您的所有投入.托马斯回答了我原来的问题.
在第一次编辑中回答我自己的问题:
我尝试将一个大的列表分成块然后将异步应用于每个子列表.
let pmapchunk f xs =
let chunks = chunk chunksize xs
seq { for chunk in chunks -> async { return (Seq.map f) chunk } }
|> Async.Parallel
|> Async.RunSynchronously
|> Seq.concat …
Run Code Online (Sandbox Code Playgroud) 我的目标是具有并行折叠功能.起初,它似乎很容易实现,这就是我的想法:
首先根据核心数(numCapabilities
)将输入列表分解为分区.然后将foldr应用于每个分区,这将导致每个分区的折叠值列表.然后在该列表上再次执行折叠以获取最终值.
listChunkSize = numCapabilities
chunk n [] = []
chunk n xs = ys : chunk n zs
where (ys,zs) = splitAt n xs
parfoldr f z [] = z
parfoldr f z xs = res
where
parts = chunk listChunkSize xs
partsRs = map (foldr f z) parts `using` parList rdeepseq
res = foldr f z partsRs
Run Code Online (Sandbox Code Playgroud)
上面的代码不起作用,因为很明显foldr的定义(a -> b -> b) -> b -> [a] -> b
意味着输入列表类型(好,可以)与累加器和结果类型不同.
例如,
1)foldr (+) 0 [1..10] …
似乎foldr
与列表理解有某种融合,因此与(21mb)相比,它需要更少的内存(11mb)分配foldl
,例如
myfunc = sum $ foldr g acc [ f x | x <- xs ]
f x = ..
g x y = ..
Run Code Online (Sandbox Code Playgroud)
有谁可以解释如何以及为什么?另外,懒惰的评价如何帮助.
假设一台机器有8个核心.在Haskell中,您可以使用该threaded
选项进行编译,然后在运行时使用期间+RTS -Nx
指定要使用的核心数.例如
$ myprg args // sequential run
$ myprg args +RTS -N1 // parallel run on 1..8 cores
$ myprg args +RTS -N2
$ myprg args +RTS -N4
$ myprg args +RTS -N8
Run Code Online (Sandbox Code Playgroud)
通过这种方式,您可以使用越来越多的内核获得运行时,然后您可以使用这些内核来获得加速并绘制图形.
如果我有一个并行程序,例如在代码中使用并行映射,你将如何在F#中执行此操作?
编辑:
我发现有ParallelOptions,例如MaxDegreeOfParallelism
,这可能是我需要但不确定它的确切行为,我必须以编程方式使用它,只要它的行为符合预期,即MaxDegreeOfParallelism
=核心程序应使用的数量,并且不是并行的'任务'或线程.
编辑:
ProcessorAffinity
确实限制了使用的核心数量,但似乎它没有在Mono中正确实现.我检查了Windows,它似乎工作.虽然使用它并不是一个好主意.运行时系统应该能够更好地决定如何管理和安排任务.此外,MaxDegreeOfParallelism
关于"并行度"基本上设置了生成的任务数,因此可用于改变粒度.