我不明白F#中的价值限制是如何运作的.我已经阅读了wiki中的解释以及MSDN文档.我不明白的是:
例如,为什么这给了我一个价值限制错误(取自这个问题):
let toleq (e:float<_>) a b = (abs ( a - b ) ) < e
Run Code Online (Sandbox Code Playgroud)
但这不是:
let toleq e (a:float<_>) b = (abs ( a - b ) ) < e
Run Code Online (Sandbox Code Playgroud)这一点可以概括......
let is_bigger a b = a < b
Run Code Online (Sandbox Code Playgroud)
但这不是(它被指定为int):
let add a b = a + b
Run Code Online (Sandbox Code Playgroud)为什么带隐式参数的函数会生成值限制:
这个:
let item_count = List.fold (fun acc _ -> 1 + acc) 0
Run Code Online (Sandbox Code Playgroud)
对此:
let item_count l = List.fold (fun acc _ …Run Code Online (Sandbox Code Playgroud)我正在尝试通过将一些C#算法重写为惯用的F#来学习F#.
我正在尝试重写的第一个函数之一是batchesOf,其中:
[1..17] |> batchesOf 5
Run Code Online (Sandbox Code Playgroud)
哪个会将序列分成多个批次,每个最多五个,即:
[[1; 2; 3; 4; 5]; [6; 7; 8; 9; 10]; [11; 12; 13; 14; 15]; [16; 17]]
Run Code Online (Sandbox Code Playgroud)
我第一次尝试这样做有点丑陋,我在尝试在闭包内部使用可变类型时遇到错误而使用了一个可变的ref对象.使用ref特别不愉快,因为要取消引用它你必须使用!在一个条件表达式内部的操作符可以与某些开发人员相反直观,这些开发人员将其视为逻辑不符合.我遇到的另一个问题是Seq.skip和Seq.take与他们的Linq别名不同,如果大小超过序列的大小,他们将抛出错误.
let batchesOf size (sequence: _ seq) : _ list seq =
seq {
let s = ref sequence
while not (!s |> Seq.isEmpty) do
yield !s |> Seq.truncate size |> List.ofSeq
s := System.Linq.Enumerable.Skip(!s, size)
}
Run Code Online (Sandbox Code Playgroud)
无论如何,在F#中重写这个最优雅/惯用的方法是什么?保持原始行为但最好没有ref可变变量.
背景:
我有一系列连续的,带时间戳的数据.数据序列中存在间隙,其中数据不连续.我想创建一种方法将序列分成序列序列,以便每个子序列包含连续数据(在间隙处分割输入序列).
约束:
方法签名
let groupContiguousDataPoints (timeBetweenContiguousDataPoints : TimeSpan) (dataPointsWithHoles : seq<DateTime * float>) : (seq<seq< DateTime * float >>)= ...
Run Code Online (Sandbox Code Playgroud)
从表面上看,问题看起来微不足道,但即使采用Seq.pairwise,IEnumerator <_>,序列理解和屈服声明,解决方案也让我望而却步.我确信这是因为我仍然缺乏组合F#-idioms的经验,或者可能是因为我还没有接触过一些语言结构.
// Test data
let numbers = {1.0..1000.0}
let baseTime = DateTime.Now
let contiguousTimeStamps = seq { for n in numbers ->baseTime.AddMinutes(n)}
let dataWithOccationalHoles = Seq.zip contiguousTimeStamps numbers |> Seq.filter (fun (dateTime, num) -> num % 77.0 <> 0.0) // Has a gap in the data every …Run Code Online (Sandbox Code Playgroud) 我应该分割seq<a>成seq<seq<a>>由所述元件的一个属性.如果此属性等于给定值,则必须在该点处"拆分".我怎么能在FSharp中做到这一点?
如果必须在该项目中进行拆分,则将"函数"传递给它并返回bool应该是不错的.
示例:输入序列:seq: {1,2,3,4,1,5,6,7,1,9}
当它等于1时,应在每个项目上进行拆分,因此结果应为:
seq
{
seq{1,2,3,4}
seq{1,5,6,7}
seq{1,9}
}
Run Code Online (Sandbox Code Playgroud) (我知道这个问题,但它与序列有关,这不是我的问题)
鉴于此输入(例如):
let testlist =
[
"*text1";
"*text2";
"text3";
"text4";
"*text5";
"*text6";
"*text7"
]
let pred (s:string) = s.StartsWith("*")
Run Code Online (Sandbox Code Playgroud)
我希望能够调用MyFunc pred testlist并获得此输出:
[
["*text1";"*text2"];
["*text5";"*text6";"*text7"]
]
Run Code Online (Sandbox Code Playgroud)
这是我目前的解决方案,但我真的不喜欢嵌套的List.revs(忽略它需要Seq作为输入的事实)
let shunt pred sq =
let shunter (prevpick, acc) (pick, a) =
match pick, prevpick with
| (true, true) -> (true, (a :: (List.hd acc)) :: (List.tl acc))
| (false, _) -> (false, acc)
| (true, _) -> (true, [a] :: acc)
sq
|> Seq.map (fun a -> (pred …Run Code Online (Sandbox Code Playgroud)