Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net F#-不理解函数的组成(将get files函数转换为get replicate files函数)_.net_F#_Functional Programming_Composition - Fatal编程技术网

.net F#-不理解函数的组成(将get files函数转换为get replicate files函数)

.net F#-不理解函数的组成(将get files函数转换为get replicate files函数),.net,f#,functional-programming,composition,.net,F#,Functional Programming,Composition,这是我的问题。。。我不明白为什么这对我不起作用:) 更具体地说,我有一个获取文件功能(这不是问题,但欢迎反馈): 这给了我一个Seq.groupBy LengthAndExtension上的编译错误 错误在于类型“b->seq”与类型“seq正向合成(>)不兼容。它创建了一个新函数,将第一个函数的输出作为输入传递给第二个函数 签名揭示了问题:(>>):('T1->'T2)->('T2->'T3)->'T1->'T3 它接受两个函数,每个函数接受一个参数。但是GetFiles需要两个参数。一个快速

这是我的问题。。。我不明白为什么这对我不起作用:)

更具体地说,我有一个获取文件功能(这不是问题,但欢迎反馈):

这给了我一个Seq.groupBy LengthAndExtension上的编译错误 错误在于类型“b->seq”与类型“seq正向合成(
>
)不兼容。它创建了一个新函数,将第一个函数的输出作为输入传递给第二个函数

签名揭示了问题:
(>>):('T1->'T2)->('T2->'T3)->'T1->'T3


它接受两个函数,每个函数接受一个参数。但是
GetFiles
需要两个参数。一个快速的解决方案是更改
GetFiles
以获取元组:
让GetFiles(dir,extlist)=……
使用函数组合
>
,我们有:
(f>>g)x=g(f(x))
。这意味着我们首先对输入应用
f
,然后对输出应用
g

使用函数组合的一种简单方法是先使用管道编写函数,然后再对其进行重构。我通常以
x>f1>f2>fn
,删除输入
x
,并将管道(
|>
)更改为函数合成(
>
),以具有正确的合成函数
f1>>f2>…>>fn
。但是,在您的示例中并不明显:

let GetDuplicateFiles(dir, extlist) =
    //...
    GetFiles dir extlist
    |> Seq.groupBy LengthAndExtension
    |> Seq.filter GroupSizeGreaterThanOne
    |> Seq.collect groups
    |> Seq.groupBy content
    |> Seq.filter GroupSizeGreaterThanOne
    |> Seq.collect groups
如果将
GetFiles
从当前形式的
GetFiles dir extlist
更改为元组形式的
GetFiles(dir,extlist)
,则可以轻松应用上述技巧来使用函数组合

另外,您可以更改
Seq.filter…>>顺序收集
顺序选择…>>Seq.concat
要在序列中保存一次遍历,请执行以下操作:

let GetDuplicateFiles =
    //...

// (dir, extlist)
// |>
    GetFiles
    >> Seq.groupBy LengthAndExtension
    >> Seq.choose GroupSizeGreaterThanOne
    >> Seq.concat
    >> Seq.groupBy content
    >> Seq.choose GroupSizeGreaterThanOne
    >> Seq.concat
GroupSizeGreaterThanOne
功能略有更改:

let GroupSizeGreaterThanOne (_, values) =
    if Seq.length values > 1 then Some values else None

这是否意味着F#函数组合和数学组合略有不同,而让F#模拟数学的方法是将n个输入包装成一个元组?很好,但还行。我的代码现在可以用了,谢谢。原因是函数不能有多个返回值。元组是实现这一点的方法。我认为您的代码更干净,但遍历保存在哪里?
Seq.collect
基本上是
Seq.map
后面是
Seq.concat
。通过保存遍历,我的意思是您可以删除不必要的
Seq.map
。Seq.collect不是与序列的一元绑定相同吗?另外,Seq.collect、Seq.map、Seq.concat是否都很懒,这意味着我不保存序列本身的遍历,而是在堆栈上保存一个额外的调用?
let GetDuplicateFiles =
    //...

// (dir, extlist)
// |>
    GetFiles
    >> Seq.groupBy LengthAndExtension
    >> Seq.choose GroupSizeGreaterThanOne
    >> Seq.concat
    >> Seq.groupBy content
    >> Seq.choose GroupSizeGreaterThanOne
    >> Seq.concat
let GroupSizeGreaterThanOne (_, values) =
    if Seq.length values > 1 then Some values else None