go
worker tail-recursive loop pattern似乎非常适合编写纯代码.为ST
monad 编写这种循环的等效方法是什么?更具体地说,我想避免循环迭代中的新堆分配.我的猜测是它涉及任一CPS transformation
或fixST
重新写使得所有在跨越环路改变的值被在每个迭代中通过,从而使寄存器的位置(或在溢出的情况下,叠加)适用于在可迭代这些值的代码.我在下面有一个简化的示例(不要尝试运行它 - 它可能会因为分段错误而崩溃!),其中涉及一个findSnakes
具有go
工作模式的函数,但更改的状态值不通过累加器参数传递:
{-# LANGUAGE BangPatterns #-}
module Test where
import Data.Vector.Unboxed.Mutable as MU
import Data.Vector.Unboxed as U hiding (mapM_)
import Control.Monad.ST as ST
import Control.Monad.Primitive (PrimState)
import Control.Monad as CM (when,forM_)
import Data.Int
type MVI1 s = MVector (PrimState (ST s)) Int
-- function to find previous y
findYP :: MVI1 s -> Int -> Int -> ST s Int
findYP fp …
Run Code Online (Sandbox Code Playgroud) 我正在学习Haskell,使用项目Euler问题作为我的游乐场.我的Haskell程序与其他语言编写的类似程序相比有多慢,我感到震惊.我想知道我是否预测过某些东西,或者这是否是在使用Haskell时所期望的那种性能损失.
以下程序受到问题331的启发,但我在发布之前已经改变了它,所以我不会为其他人破坏任何东西.它计算在2 ^ 30 x 2 ^ 30网格上绘制的离散圆的弧长.这是一个简单的尾递归实现,我确保累积变量的更新跟踪弧长是严格的.然而,它需要将近一分半钟的时间才能完成(使用-O标志和ghc编译).
import Data.Int
arcLength :: Int64->Int64
arcLength n = arcLength' 0 (n-1) 0 0 where
arcLength' x y norm2 acc
| x > y = acc
| norm2 < 0 = arcLength' (x + 1) y (norm2 + 2*x +1) acc
| norm2 > 2*(n-1) = arcLength' (x - 1) (y-1) (norm2 - 2*(x + y) + 2) acc
| otherwise = arcLength' (x + 1) y (norm2 + 2*x + 1) $! …
Run Code Online (Sandbox Code Playgroud) 考虑以下问题:给定一个长度为三的元组列表(String,Int),是否有一对具有相同"Int"部分的元素?(例如,[("bob",5),("gertrude",3),("al",5)]
包含这样一对,但[("bob",5),("gertrude",3),("al",1)]
不包含.)
这就是我实现这样一个功能的方法:
import Data.List (sortBy)
import Data.Function (on)
hasPair::[(String,Int)]->Bool
hasPair = napkin . sortBy (compare `on` snd)
where napkin [(_, a),(_, b),(_, c)] | a == b = True
| b == c = True
| otherwise = False
Run Code Online (Sandbox Code Playgroud)
我已经使用模式匹配将名称绑定到元组的"Int"部分,但我想先排序(为了像成员一样分组),所以我将模式匹配函数放在where
子句中.但这让我想到了一个where
问题:为条款中的函数选择名称有什么好的策略?我希望能够迅速想到这些名字.对于这个例子,"hasPair"似乎是一个不错的选择,但它已经被采用了!我发现这个模式出现了很多 - 辅助函数的自然看似名称已被调用它的外部函数占用.因此,我有时会称这样的帮助函数为"op","foo",甚至是"helper" - 在这里我选择了"餐巾"来强调它的使用 - 一次性,扔掉它的性质.
那么,亲爱的Stackoverflow读者,你会称之为"餐巾纸"?更重要的是,您如何处理这个问题?
对于常见的方法类型,C#有一些命名约定:
BeginFoo()
/ EndFoo()
用于异步方法TryGet()
/ TryParse()
返回false
而不是抛出异常FooOrDefault()
对于返回default(T)
而不是抛出异常的方法IsFoo
对于布尔标志我想知道,有一个递归的内部方法吗?例如,在此示例中来自另一个Stack Overflow问题:
public int CalculateSomethingRecursively(int someNumber)
{
return doSomethingRecursively(someNumber, 0);
}
// What to call this?
private int doSomethingRecursively(int someNumber, int level)
{
if (level >= MAX_LEVEL || !shouldKeepCalculating(someNumber))
return someNumber;
return doSomethingRecursively(someNumber, level + 1);
}
Run Code Online (Sandbox Code Playgroud)
在CI中,人们使用foo(...)
+ foo_r(...)
作为惯例.但是在.NET中怎么样?
在Haskell中,当我需要快速工作函数或辅助值时,我通常使用'
广泛用于数学的prime().例如,如果我要编写一个reverse
函数并且需要一个尾递归工作器,我会命名它reverse'
.
在Scala中,函数名称不能包含'
.Scala中是否有任何常用的辅助函数和值的命名方案?