什么是“monadic反射”?
如何在F#-program中使用它?
术语“反射”的含义是否与.NET反射相同?
答案 0 :(得分:8)
Monadic反射本质上是用于描述分层monad或monad分层的语法。在Haskell中,描述也意味着构建monad。这是一个更高级别的系统,所以代码看起来像功能,但结果是monad组合 - 意味着如果没有实际的monad(它们是无功能的),那么在一天结束时没有任何真实/可运行的东西。菲林斯基最初试图将一种monad仿真用于Scheme,但更多的是探索monad的理论方面。
评论更正 - F#有Monad等效名为"Computation Expressions"
Filinski's paper at POPL 2010 - 没有代码,但有很多理论,当然还有他1994年的原始论文 - Representing Monads。加上一个代码:Monad Transformers and Modular Interpreters(1995)
哦,对于喜欢代码的人 - Filinski's code是在线的。我只列出一个 - 走一步,看另一个7和自述。同样只是a bit of F# code声称受到Filinski的启发
答案 1 :(得分:3)
我读了第一篇Google热门文章,其中有一些幻灯片:
http://www.cs.ioc.ee/mpc-amast06/msfp/filinski-slides.pdf
从这看起来像
Oleg Kiselyov也有an article,但我甚至没有尝试阅读它。还有一篇来自Jonathan Sobel(等)的论文。命中5是这个问题,所以我不再照顾它了。
答案 2 :(得分:1)
如前面的答案链接所述,Monadic reflection是bridge call/cc style and Church style programming的概念。更多地描述这两个概念:
使用自定义构建器类型创建F# Computation expressions(= monads)。
Don Syme有一个很好的blog post about this。如果我编写代码来使用构建器并使用如下语法:
attempt { let! n1 = f inp1
let! n2 = failIfBig inp2
let sum = n1 + n2
return sum }
语法被翻译为call/cc "call-with-current-continuation"样式程序:
attempt.Delay(fun () ->
attempt.Bind(f inp1,(fun n1 ->
attempt.Bind(f inp2,(fun n2 ->
attempt.Let(n1 + n2,(fun sum ->
attempt.Return(sum))))))))
最后一个参数是下一个要执行的命令,直到结束。
(计划式编程。)
F#基于OCaml。
F#具有部分功能应用,但它也是强类型的并且具有值限制 但OCaml没有价值限制。
OCaml可用于Church类编程,其中组合函数用于构造任何其他函数(或程序):
// S K I combinators:
let I x = x
let K x y = x
let S x y z = x z (y z)
//examples:
let seven = S (K) (K) 7
let doubleI = I I //Won't work in F#
// y-combinator to make recursion
let Y = S (K (S I I)) (S (S (K S) K) (K (S I I)))
Church numerals是一种用纯函数表示数字的方法。
let zero f x = x
//same as: let zero = fun f -> fun x -> x
let succ n f x = f (n f x)
let one = succ zero
let two = succ (succ zero)
let add n1 n2 f x = n1 f (n2 f x)
let multiply n1 n2 f = n2(n1(f))
let exp n1 n2 = n2(n1)
这里,零是一个函数,它将两个函数作为参数:f应用零次,因此这表示数字为零,x用于其他计算中的函数组合(如add)。 succ函数就像plusOne所以one = zero |> Plusone精选。
要执行这些函数,最后一个函数将使用last参数(x)调用其他函数为空。
(Haskell式编程。)
在F#中,限制值很难。 Church numerals can be made with C# 4.0 dynamic keyword(里面使用.NET反射)。我认为在F#中还有相同的解决方法。