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
F# 函数合成依赖于部分应用吗?_F#_Functional Programming - Fatal编程技术网

F# 函数合成依赖于部分应用吗?

F# 函数合成依赖于部分应用吗?,f#,functional-programming,F#,Functional Programming,函数合成依赖于部分应用吗 以下是我的理解: 观察以下函数是否存在函数调用重复: let updateCells (grid:Map<(int * int), Cell>) = grid |> Map.toSeq |> Seq.map snd |> Seq.fold (fun grid c -> grid |> setReaction (c.X, c.Y)) grid let mutable _cells =

函数合成依赖于部分应用吗

以下是我的理解: 观察以下函数是否存在函数调用重复:

let updateCells (grid:Map<(int * int), Cell>) =

    grid |> Map.toSeq
         |> Seq.map snd
         |> Seq.fold (fun grid c -> grid |> setReaction (c.X, c.Y)) grid

let mutable _cells = ObservableCollection<Cell>( grid |> Map.toSeq
                                                      |> Seq.map snd
                                                      |> Seq.toList )
let cycleHandler _ = 

    self.Cells <- ObservableCollection<Cell>( grid |> cycleThroughCells
                                                   |> Map.toSeq
                                                   |> Seq.map snd
                                                   |> Seq.toList )
功能组合

在函数式编程中,我们可以将函数融合在一起,使它们成为一个函数

为此,让我们从复制的函数序列中创建一个新函数:

grid |> Map.toSeq
     |> Seq.map snd
let getCells = Map.toSeq >> Seq.map snd >> Seq.toList
现在,如果您注意到了,您会注意到,在使用函数组合时,我们不使用任何参数。因此,不使用栅格值。这背后的原因是部分应用

部分应用

我还在学习所有这些函数式编程技术。然而,我的理解是,部分应用程序是函数编程中的一种技术,它推迟了接受给定函数的完整参数集的需要。换句话说,部分应用是延迟接受给定函数的完整参数集的行为,其中期望最终客户机稍后提供其余参数。至少,这是我的理解

我们现在可以使用如下函数:

let updateCells (grid:Map<(int * int), Cell>) =

    grid |> Map.toSeq
         |> Seq.map snd
         |> Seq.fold (fun grid c -> grid |> setReaction (c.X, c.Y)) grid
let updateCells (grid:Map<(int * int), Cell>) =

    grid |> getCells
         |> Seq.fold (fun grid c -> grid |> setReaction (c.X, c.Y)) grid
let updateCells(网格:Map)=
网格|>Map.toSeq
|>序列图snd
|>Seq.fold(趣味网格c->grid |>setReaction(c.X,c.Y))网格
并将其重构为:

let updateCells (grid:Map<(int * int), Cell>) =

    grid |> Map.toSeq
         |> Seq.map snd
         |> Seq.fold (fun grid c -> grid |> setReaction (c.X, c.Y)) grid
let updateCells (grid:Map<(int * int), Cell>) =

    grid |> getCells
         |> Seq.fold (fun grid c -> grid |> setReaction (c.X, c.Y)) grid
let updateCells(网格:Map)=
网格|>getCells
|>Seq.fold(趣味网格c->grid |>setReaction(c.X,c.Y))网格

我关于函数组合与部分应用程序结合的想法是否准确?

这更多的是评论,而不是答案,因为评论太多了

我从堆栈中提取参数的方法是使用
fun
关键字

// Standard function with arguments
let add1 x y  = x + y

// Function defining no arguments.  
// I think of the arguments x and y as being on the stack.
let add2 = (+)

// Function defining no arguments.  
// I think of the arguments x and y as being on the stack 
// and being given the names x and y.
let add3 = fun x y -> x + y

let result1 = add1 1 2
printfn "add1: %A" result1

let result2 = add2 1 2
printfn "add2: %A" result2

let result3 = add3 1 2
printfn "add3: %A" result3
发送到F#interactive Products时

val add1 : x:int -> y:int -> int

val add2 : (int -> int -> int)

val add3 : x:int -> y:int -> int

val result1 : int = 3
add1: 3
val it : unit = ()

val result2 : int = 3
add2: 3
val it : unit = ()

val result3 : int = 3
add3: 3
val it : unit = ()
另一个例子是使用
函数
关键字

let charType =
    function
    | n when n >= '0' && n <= '9' -> "number"
    | l when l >= 'a' && l <= 'z' -> "lower case"
    | u when u >= 'A' && u <= 'Z' -> "upper case"
    | _ ->  "other"

let result4 = charType '0'
printfn "charType '0': %A" result4
let charType=
功能
|n当n>='0'&&n“编号”时为n
|当l>='a'&&l“小写”时为l
|当u>='A'&&u“大写”时的u
|——>“其他”
让result4=图表类型“0”
printfn“图表类型“0”:%A”结果4
组合取决于一级函数,而不是部分应用程序

实现组合所需的是:

  • 函数必须能够作为参数并作为返回值返回
  • 函数签名必须是有效类型(如果希望组合为强类型)
部分应用程序为组合创造了更多的机会,但原则上,您可以在没有它的情况下轻松定义函数组合

例如,C#没有部分应用程序*,但您仍然可以将两个函数组合在一起,只要签名匹配:

Func Compose(此函数,
Func(g)
{
返回x=>g(f(x));
}
这是一个语法更难看的语法:
f.Compose(g)

然而,在组合和部分应用程序之间有一个有趣的联系。
>
运算符的定义为:

let (>>) f g x = g(f(x))
因此,当您编写
foo>>bar
时,您确实部分地应用了
(>>)
函数,即省略
x
参数以获得
fun x=g(f(x))
部分结果

但是,正如我上面所说的,这并不是绝对必要的。上面的
Compose
函数相当于F#的
>
操作符,不涉及任何部分应用;lambda以稍微详细一点的方式执行相同的角色


*除非您手动实现它,否则没有人会这样做。也就是说,不写

stringfoo(inta,intb)
{ 
return(a+b).ToString();
}
你得写信

Func-foo(int-a)
{ 
返回b=>(a+b).ToString();
}
然后你就可以像在F#中一样分别传递每个参数。

泛型 实际上,如果你接受这个表达式

let getCells = Map.toSeq >> Seq.map snd >> Seq.toList
如果尝试将其编译为独立表达式,则会出现编译器错误:

错误FS0030:值限制。已推断值“getCells”具有泛型类型 val getCells:(映射->“\u b列表)何时“\u a:比较
使“getCells”的参数显式,或者,如果不希望它是泛型的,则添加类型注释

它在您的案例中起作用的原因是,您将
getCells
函数与
grid
一起使用,这意味着编译器推断它具有约束类型

为了保持通用性,您可以使用显式参数对其进行重新表述:

let getCells xs = xs |> Map.toSeq |> Seq.map snd |> Seq.toList
当“a:比较”时,此表达式是类型为
Map->“b列表”的有效独立表达式

无点 调用与
>
函数组合运算符一起使用的样式。它适用于部分应用程序,但并不完全相同

应用 然而,本例中有一个部分函数应用示例:

let getCells xs = xs |> Map.toSeq |> Seq.map snd |> Seq.toList
功能
snd
具有以下类型:

'a * 'b -> 'b
函数只接受一个参数

您也可以编写上述
getCells
函数,而不必部分应用
snd
函数:

let getCells xs = xs |> Map.toSeq |> Seq.map (fun x -> snd x) |> Seq.toList
Seq.map snd
请注意,您可以传递lambda表达式,而不是传递给
Seq.map
的部分应用函数。
getCells
函数仍然是由其他函数组成的函数,但它不再依赖于部分应用
snd

因此,部分(双关语)回答您的问题:函数组合不必依赖于部分函数组合。

咖喱 在F#中,默认情况下会使用函数。这意味着所有函数只接受一个参数,并返回一个值。有时(经常),t