我们这里真的很开心.我已经在数据的具体表示上测试了一堆树同步代码,现在我需要对它进行抽象,以便它可以运行任何支持正确方法的源和目标.[实际上,这将是Documentum,SQL层次结构和文件系统等来源; 使用Solr和自定义SQL交叉引用存储等目标.
棘手的部分是,当我递归一个类型的树T并同步到一个类型的树时U,在某些文件中,我需要在当前节点处对该类型V执行第二种类型的"子同步" U.(V代表阶层结构的内部文件......),并在F#的类型推理引擎将立即围绕推动我在圈子里就这一点,因为我尝试添加子同步到V.
我在一个代表这个TreeComparison<'a,'b>,所以上面的东西导致a TreeComparison<T,U>和子比较TreeComparison<V,U>.
问题是,只要我TreeComparison<V,'b>在其中一个类方法中提供具体V,当我希望第一个类型参数保持泛型(when 'a :> ITree)时,类型会传播所有推断.也许我可以对TreeComparison<V,'b>价值做一些打字?或者,更有可能的是,推断实际上告诉我,在我思考这个问题的方式中,某些东西本来就被打破了.
这对于压缩来说真的很棘手,但是我想给你可以粘贴到脚本中的工作代码并进行实验,所以一开始就有很多类型......如果你想跳过,核心内容就在最后.通过ITree对大多数类型的实际比较和递归进行了切割,因为没有必要看到我正在敲打的推理问题.
open System
type TreeState<'a,'b> = //'
| TreeNew of 'a
| TreeDeleted of 'b
| TreeBoth of 'a * 'b
type TreeNodeType = TreeFolder | TreeFile | TreeSection
type ITree =
abstract NodeType: TreeNodeType
abstract Path: string
with get, set
type ITreeProvider<'a when …Run Code Online (Sandbox Code Playgroud) 我在hubFS上发现了这个问题,但它根据各个元素处理分裂标准.我想根据相邻元素的比较进行拆分,因此类型如下所示:
val split = ('T -> 'T -> bool) -> 'T list -> 'T list list
Run Code Online (Sandbox Code Playgroud)
目前,我试图从Don的必要解决方案开始,但我无法弄清楚如何初始化和使用'prev'值进行比较.折叠更好的方式去?
//Don's solution for single criteria, copied from hubFS
let SequencesStartingWith n (s:seq<_>) =
seq { use ie = s.GetEnumerator()
let acc = new ResizeArray<_>()
while ie.MoveNext() do
let x = ie.Current
if x = n && acc.Count > 0 then
yield ResizeArray.to_list acc
acc.Clear()
acc.Add x
if acc.Count > 0 then
yield ResizeArray.to_list acc }
Run Code Online (Sandbox Code Playgroud) 是否可以部分应用诸如bprintf并根据其初始使用限制其功能?
我想做以下事情:
let builder = new System.Text.StringBuilder()
let append = Printf.bprintf builder
append "%i" 10
append "%s" string_value
Run Code Online (Sandbox Code Playgroud) 我Queue在F#中创建了一个不可变的如下:
type Queue<'a>(f : 'a list, r : 'a list) =
let check = function
| [], r -> Queue(List.rev r, [])
| f, r -> Queue(f, r)
member this.hd =
match f with
| [] -> failwith "empty"
| hd :: tl -> hd
member this.tl =
match f, r with
| [], _ -> failwith "empty"
| hd::f, r -> check(f, r)
member this.add(x) = check(f, x::r)
static member empty : Queue<'a> = Queue([], [])
Run Code Online (Sandbox Code Playgroud)
我想创建一个空的实例 …
let inline myfunction x y = ...
let inline mycurried = myfunction x // error, only functions may be marked inline
Run Code Online (Sandbox Code Playgroud)
显然inlinecurried函数似乎是不可能的.因此,无论何时mycurried被调用,inlined即使myfunction是inlined正确的也不会得到,是否正确?
那么这可以被视为咖喱功能的缺点之一吗?
我已经阅读了F#中关于价值限制的所有内容,但我仍然不理解它.我有以下代码:
type tree<'a> =
| Nil
| Node of (tree<'a> * 'a * tree<'a>)
let rec flatten = function
| Nil -> []
| Node ( Nil, b, Nil ) -> [b]
| Node ( l, h, p ) -> List.concat [(flatten l);[h];(flatten p)]
Run Code Online (Sandbox Code Playgroud)
并且编译器显示错误:
error FS0030: Value restriction. The value 'it' has been inferred to have generic type
val it : '_a list
Either define 'it' as a simple data term, make it a function with explicit arguments or, …Run Code Online (Sandbox Code Playgroud) 考虑以下:
type T () =
member x.y = 4
let a =
let fn () (k: T) = ()
fn ()
let b =
let fn () (k: System.IO.Directory) = ()
fn ()
Run Code Online (Sandbox Code Playgroud)
a没错,b一切都好.错误消息是:
值'a'被推断为具有泛型类型val a:('_a - > unit)当'_a:> T要么将参数设为'a'显式,要么如果你不打算使它是通用的,添加类型注释
为什么以及如何解决这个问题?
我试图使用库中的pipe3函数,FParsec但我得到一个错误,我不知道如何解决.
鉴于记录
type Point = { x: float; y: float }
Run Code Online (Sandbox Code Playgroud)
和以下解析器
let plistoffloats' =
pipe3 pfloat (pchar ',' .>> spaces) pfloat
(fun first z second -> { x = first; y = second })
Run Code Online (Sandbox Code Playgroud)
我试图实现的是一个解析器,它接收格式的字符串"1.1, 3.7"并返回一个Point
run plistoffloats' "1.1, 3.7"
Run Code Online (Sandbox Code Playgroud)
输入:"1.1, 3.7"
期望的输出:Point = {x = 1.1; y = 3.7;}
错误:
错误FS0030:值限制.值'plistoffloats''被推断为具有泛型类型val plistoffloats':
Parser <Point,'__a>
将'plistoffloats'的参数显式化,或者,如果您不打算将它作为泛型,则添加类型注释.
一个更简单的例子pchar也没有用.
let parsesA = pchar 'a'
Run Code Online (Sandbox Code Playgroud)
错误FS0030:值限制.值'parsesA'被推断为具有泛型类型val parsesA:
Parser<char,'_a> …
我正在学习 F#。我来这里是因为我对价值限制有一些难以理解的事情。
\n\n以下是我正在学习的书中的示例。
\n\nlet mapFirst = List.map fst\nRun Code Online (Sandbox Code Playgroud)\n\n由于我用 haskell 学习了 FP,所以我非常确定这段代码可以很好地编译,但事实并非如此。结果出现错误FS0030(抱歉,我无法复制粘贴 fsi 错误消息,因为它是用韩语编写的)。相反,我必须提供一个明确的论点,例如:
let mapFirst inp = List.map fst inp // or inp |> List.map fst\nRun Code Online (Sandbox Code Playgroud)\n\n但为什么?我认为通过上面的例子,编译器肯定可以推断出给定值的类型:
\n\nlet mapFirst inp = List.map fst inp // or inp |> List.map fst\nRun Code Online (Sandbox Code Playgroud)\n\n如果我没记错的话,我在 haskell 中调用了这个东西eta-conversion,上面两个例子是完全相同的。(但也许不完全是)。为什么我应该显式地向可以柯里化的函数提供参数而不丢失任何信息?
\n\n我明白了类似的事情
\n\nval mapFirst : (\'a * \'b) list -> \'a list\nRun Code Online (Sandbox Code Playgroud)\n\n不会编译,为什么,但我不认为它与我的问题有关。
\n\n\xe2\x80\xbb 我看了一下这个问题,但没有帮助。
\n我正在寻找一种方法来解决这个非常特殊的情况:我有一个函数工厂toF,它接受一个函数参数g并基于它创建一个结果函数f
let toF g =
let f x = g x
f
let f = toF id
Run Code Online (Sandbox Code Playgroud)
问题是我得到了
error FS0030: Value restriction. The value 'f' has been inferred to have generic type val f : ('_a -> '_a) Either make the arguments to 'f' explicit or, if you do not intend for it to be generic, add a type annotation.
Run Code Online (Sandbox Code Playgroud)
我可以添加类型注释(我不急于做)或者我可以像这样重写它:
let f' g x = g x
let f x = f' id x …Run Code Online (Sandbox Code Playgroud) let csvList startDelim endDelim lst memF =
let listIter (listStr: string) item =
if listStr.Length > 0 then
listStr + "," + (memF item)
else
memF item
startDelim + (List.fold listIter "" lst) + endDelim
let listIntoJsonArray = csvList "[" "]"
let listIntoJsonObject = csvList "{" "}"
let intConverter (item:int) : string =
item.ToString()
let objectConverter (item:SomeObject) : string =
item.value.ToString()
let objects = [{vaue: 12.3}; {vaule: 33.2}]
let ints = [1;2;4]
let o = listIntoJsonObject objects objectConverter
let i …Run Code Online (Sandbox Code Playgroud) 我对函数式编程有点新意,虽然我对F#有点熟悉,但我仍然在学习所有奇怪的工作方式.
//I love my Rice and Curry'd functions
let add x =
let subFunction y =
x + y
subFunction
//explicit parameter
let add1 y = add 1 y
//implicit parameter
let add10 = add 10
//calling it with the parameter it doesn't show that it takes
let twenty = add10 10
Run Code Online (Sandbox Code Playgroud)
所以这里add10有隐式参数,因为它调用的函数返回一个带参数的函数.为什么我接受我可以这样声明它而不是我声明add1的方式?
从它的声明判断它真的具有欺骗性,人们会假设它只是一个int.