小编pri*_*tor的帖子

如何编写通用数字的函数?

我对F#很陌生,发现类型推断确实很酷.但目前似乎它也可能导致代码重复,这不是一件很酷的事情.我想总结一个这样的数字的数字:

let rec crossfoot n =
  if n = 0 then 0
  else n % 10 + crossfoot (n / 10)

crossfoot 123
Run Code Online (Sandbox Code Playgroud)

这正确打印6.但是现在我的输入数字不适合32位,所以我必须将其转换为.

let rec crossfoot n =
  if n = 0L then 0L
  else n % 10L + crossfoot (n / 10L)

crossfoot 123L
Run Code Online (Sandbox Code Playgroud)

然后,BigInteger我来了,猜猜是什么......

当然,我只能提供bigint版本和转换输入参数,并根据需要输出参数.但首先我假设使用BigInteger过度int有一些性能惩罚.第二个let cf = int (crossfoot (bigint 123))不好看.

写这个没有通用的方法吗?

generics f# types numbers type-inference

37
推荐指数
3
解决办法
4439
查看次数

(正向)管道操作员是否可以阻止尾调用优化?

对于工作中的参数优化问题,我写了一个遗传算法来找到一些好的设置,因为蛮力解决方案是不可行的.不幸的是,当我早上回来时,大部分时间我都会被送到StackOverflowException.

我已经使用F#已经有一段时间了所以我知道TCO和需要带累加器参数的函数,并且通常使用该形式.

经过大量的搜索,我认为我能够找到触发异常的代码:

breedPopulation alive |> simulate (generation + 1) lastTime ewma
Run Code Online (Sandbox Code Playgroud)

breedPopulation从当前个体中生成新一代alive.然后通过调用开始下一轮/生成simulate.当我看到反汇编(总noob)时,我发现了一些pop和a ret,所以它看起来不像是对我的常规(非尾部)调用.

mov         rcx,qword ptr [rbp+10h]  
mov         rcx,qword ptr [rcx+8]  
mov         rdx,qword ptr [rbp-40h]  
cmp         dword ptr [rcx],ecx  
call        00007FFA3E4905C0  
mov         qword ptr [rbp-0F0h],rax  
mov         r8,qword ptr [rbp-0F0h]  
mov         qword ptr [rbp-80h],r8  
mov         r8,qword ptr [rbp-78h]  
mov         qword ptr [rsp+20h],r8  
mov         r8d,dword ptr [rbp+18h]  
inc         r8d  
mov         rdx,qword ptr [rbp+10h]  
mov         r9,qword ptr [rbp-20h]  
mov         rcx,7FFA3E525960h  
call        00007FFA3E4A5040 …
Run Code Online (Sandbox Code Playgroud)

stack-overflow f# cil tail-recursion tail-call-optimization

17
推荐指数
1
解决办法
236
查看次数

我怎样才能将一个值转换回类型?

通常在F#中编写通用代码时,我会遇到与此类似的情况(我知道这非常低效,仅用于演示目的):

let isPrime n =
    let sq = n |> float |> sqrt |> int
    {2..sq} |> Seq.forall (fun d -> n % d <> 0)
Run Code Online (Sandbox Code Playgroud)

对于许多问题,我可以使用静态解析的类型,并通过内联获得性能提升.

let inline isPrime (n:^a) =
    let two = LanguagePrimitives.GenericOne + LanguagePrimitives.GenericOne
    let sq = n |> float |> sqrt |> int
    {two..sq} |> Seq.forall (fun d -> n % d <> LanguagePrimitives.GenericZero)
Run Code Online (Sandbox Code Playgroud)

由于上限序列是一个浮点数,上面的代码将无法编译.非理性地说,我可以退回到int例如.

但是编译器不允许我使用以下任何一个:

  • let sq = n |> float |> sqrt :> ^a
  • let sq = …

f# static-analysis casting compile-time

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

如何获取XAML中定义的CollectionView

我想绑定到ObservableCollectionXAML中,并在那里应用分组.原则上,这很好.

<UserControl.Resources>
    <CollectionViewSource x:Key="cvs" Source="{Binding Path=TestTemplates}">
        <CollectionViewSource.SortDescriptions>
            <scm:SortDescription PropertyName="Title"/>
        </CollectionViewSource.SortDescriptions>
        <CollectionViewSource.GroupDescriptions>
            <PropertyGroupDescription PropertyName="TestCategory"/>
        </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>
</UserControl.Resources>
Run Code Online (Sandbox Code Playgroud)

然后数据绑定表达式ItemsSource="{Binding Source={StaticResource ResourceKey=cvs}}"代替ItemsSource="{Binding Path=TestTemplates}".

起初,一切看起来都很酷,直到我想从视图模型中刷新UI.问题是,CollectionViewSource.GetDefaultView(TestTemplates)返回的视图与应用分组的XAML中的视图不同.因此,我无法设置选择或做任何有用的事情.

我可以通过将列表再次直接绑定到视图模型的属性并在代码隐藏中设置分组来修复它.但我对这个解决方案并不满意.

private void UserControlLoaded(object sender, RoutedEventArgs e)
{
    IEnumerable source = TemplateList.ItemsSource;
    var cvs = (CollectionView)CollectionViewSource.GetDefaultView(source);
    if (cvs != null)
    {
        cvs.SortDescriptions.Add(new SortDescription("Title", ListSortDirection.Ascending));
        cvs.GroupDescriptions.Add(new PropertyGroupDescription("TestCategory"));
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为,其原因已由John Skeet在此提供.

尽管如此,我希望应该有一种方法来获得正确的观点.我错了吗?

c# wpf xaml code-behind collectionviewsource

8
推荐指数
3
解决办法
4892
查看次数

实现指树时键入错误

我想用2-3个手指树来玩,如Hinze的(Haskell)论文所述(另见本博客).

type Node<'a> =
    | Node2 of 'a * 'a
    | Node3 of 'a * 'a * 'a

    static member OfList = function
        | [a; b] -> Node2(a, b)
        | [a; b; c] -> Node3(a, b, c)
        | _ -> failwith "Only lists of length 2 or 3 accepted!"

    member me.ToList () =
        match me with
        | Node2(a, b) -> [a; b]
        | Node3(a, b, c) -> [a; b; c]

type Digit<'a> =
    | One of …
Run Code Online (Sandbox Code Playgroud)

recursion f# types infinite finger-tree

7
推荐指数
1
解决办法
96
查看次数

当 lambda 工作时,为什么重写为 Julia do 块会中断?

我有这个 lambda 风格的函数调用

foldr((l,r) -> r+1, "12345"; init=0)
Run Code Online (Sandbox Code Playgroud)

Julia 很高兴地将其计算为 5。将其重写为do如下所示的样式

foldr("12345"; init=0) do (l,r)   # I also tried ((l,r),) and just tup
    # l,r = tup   # and then destructure here
    r+1
end
Run Code Online (Sandbox Code Playgroud)

据我了解,这两者应该是等价的。不幸的是,Julia 1.7.0-rc3 不同意我的观点:

错误:MethodError:没有方法匹配 (::var"#36#37")(::Char, ::Int64)
最接近的候选者是:(
::var"#36#37")(::Any) at REPL[ 25]:2
Stacktrace:
[1] FlipArgs
@ ./reduce.jl:196 [内联]
[2] BottomRF
@ ./reduce.jl:81 [内联]
[3] _foldl_impl(op::Base.BottomRF{Base. FlipArgs{var"#36#37"}}, init::Int64, itr::Base.Iterators.Reverse{String})
@ Base ./reduce.jl:58
[4] Foldl_impl(op::Base.BottomRF{ Base.FlipArgs{var"#36#37"}}, nt::Int64, itr::Base.Iterators.Reverse{String})
@ Base ./reduce.jl:48
[5] mapfoldr_impl(f::Function, op::Function、nt::Int64、itr::String)
@ Base ./reduce.jl:186 …

lambda types fold dispatch julia

7
推荐指数
1
解决办法
135
查看次数

如何在 Raku 比较方面提高性能?

我想在学习 Raku 的同时对 Python 和 Raku 进行一些比较。

\n

本来我想要一个更大的脚本,但由于差异已经很大,我现在就寻求指导。

\n

我尝试忠实地翻译这个 Python 脚本,同时应用不应该损害性能的 Raku 知识:

\n
from collections import deque\nfrom itertools import count, islice\n\n\ndef primes_wheel():\n    yield 2\n    composites = {}\n    for candidate in count(3, step=2):\n        prime = composites.pop(candidate, 0)\n        if prime:\n            while True:\n                candidate += prime + prime\n                if candidate not in composites:\n                    composites[candidate] = prime\n                    break\n        else:\n            composites[candidate * candidate] = candidate\n            yield candidate\n\n\ndef last(itr):\n    return deque(itr, 1).pop()\n\n\nLENGTH = 99999\n\nprint(last(islice(primes_wheel(), 0, LENGTH)))\n
Run Code Online (Sandbox Code Playgroud)\n

我到达了这个:

\n
sub primes_wheel {\n    my …
Run Code Online (Sandbox Code Playgroud)

performance primes generator raku

7
推荐指数
1
解决办法
279
查看次数

尽管尾部呼叫位置仍然堆栈溢出但仅在64位

源于这个问题,我有这个小F#代码(github)根据正态分布生成随机值:

// val nextSingle : (unit -> float32)
let nextSingle =
    let r = System.Random()
    r.NextDouble >> float32

// val gauss : (float32 -> float32 -> seq<float32>)
let gauss mean stdDev =
    let rec gauss ready = seq {
        match ready with
        | Some spare ->
            yield spare * stdDev + mean
            yield! gauss None
        | _ ->
            let rec loop () =
                let u = nextSingle() * 2.f - 1.f
                let v = nextSingle() * …
Run Code Online (Sandbox Code Playgroud)

stack-overflow 64-bit f# 32-bit tail-recursion

6
推荐指数
1
解决办法
122
查看次数

没有更好的方法来组合多个`Union{T, Nothing}`

我对 Julia 很陌生,但我对 Scheme/Rust/F# 有一定的了解。

今天我想让昨天的 AoC更好,而不需要明确数量的嵌套循环。

我找到了这个可行的解决方案,但我不喜欢最后一个if. 在上面提到的语言中,我会调用一个函数(或使用计算表达式),它给我的第一个结果不是None. 对于朱莉娅,我期望的东西做的。它确实如此,但出乎意料地以一种热切的方式出现。

所以当我尝试时return something(find(r, n, start + 1, which), find(r, n - 1, start + 1, extended)),当第一个参数已经有结果时,它也会评估第二个参数 - 因此崩溃。

是否有宏/懒惰版本或something我没有找到?遇到这样的案子该怎么办?

我也想过(短路)或将它们放在一起,但我猜朱莉娅在这件事上的严格破坏了这一点。

using DataStructures

function find(r::Array{Int}, n, start = 1, which = nil())::Union{Int,Nothing}
    if start <= length(r)
        extended = cons(start, which)
        with_current = sum(i -> r[i], extended)
        if with_current == 2020 && n == 1
            return prod(i -> r[i], …
Run Code Online (Sandbox Code Playgroud)

lazy-evaluation nothing optional julia

6
推荐指数
1
解决办法
85
查看次数

快速获得Eratosthenes的功能筛选

我读了这篇关于这个算法的F#版本的帖子.我发现它非常优雅,并试图结合一些答案的想法.

虽然我对它进行了优化以减少检查(仅检查6左右的数字)并省去不必要的缓存,但仍然很慢.计算10,000 素数已经超过5分钟.使用命令式方法,我可以在更长的时间内测试所有31位整数.

所以我的问题是,如果我遗漏了使这一切变得如此缓慢的事情.例如,在另一篇文章中有人猜测LazyList可能会使用锁定.有没有人有想法?

由于StackOverflow的规则说不要将新问题作为答案发布,我觉得我必须为此开始一个新主题.

这是代码:

#r "FSharp.PowerPack.dll"

open Microsoft.FSharp.Collections

let squareLimit = System.Int32.MaxValue |> float32 |> sqrt |> int

let around6 = LazyList.unfold (fun (candidate, (plus, next)) -> 
        if candidate > System.Int32.MaxValue - plus then
            None
        else
            Some(candidate, (candidate + plus, (next, plus)))
    ) (5, (2, 4))

let (|SeqCons|SeqNil|) s =
    if Seq.isEmpty s then SeqNil
    else SeqCons(Seq.head s, Seq.skip 1 s)

let rec lazyDifference l1 l2 =
    if Seq.isEmpty l2 then …
Run Code Online (Sandbox Code Playgroud)

performance primes f# lazy-evaluation sieve-of-eratosthenes

5
推荐指数
1
解决办法
656
查看次数