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
组合取决于一级函数,而不是部分应用程序
实现组合所需的是:
- 函数必须能够作为参数并作为返回值返回
- 函数签名必须是有效类型(如果希望组合为强类型)
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