对于可用的关键字数量,F#的monads实现是唯一的吗?

Cha*_*ert 15 monads f# functional-programming

我只知道F#.我还没有学过其他函数式编程语言.我在monad中看到的所有例子都只描述了bind和unit方法.F#有很多关键字(例如let!,do!等等),允许您在同一计算表达式中执行不同的操作.这似乎比你的基本绑定和单位方法更有力量.这是F#的独特之处还是在函数式编程语言中很常见?

Tom*_*cek 20

是的,我认为计算表达式的F#语法是独特的,因为它为不同类型的计算提供了直接的语法支持.它可用于处理幺半群,常用monad以及Haskell的MonadPlus计算.

我在介绍硕士论文时写到了这些.我相信它是非常易读的部分,所以你可以去第27页阅读它.无论如何,我会复制这里的例子:

Monoid仅用于使用一些"+"操作(Combine)来连接值.您可以使用它来构建字符串(这是低效的,但它证明了这个想法):

type StringMonoid() =
  member x.Combine(s1, s2) = String.Concat(s1, s2)
  member x.Zero() = ""
  member x.Yield(s) = s

let str = new StringMonoid()

let hello = str { yield "Hello "
                  yield "world!" };;
Run Code Online (Sandbox Code Playgroud)

Monads是使用comptuation表达式的绑定返回操作的常见示例.例如, monad 可能表示在任何时候都可能失败的计算:

type MaybeMonad() =
  member x.Bind(m, f) =
    match m with Some(v) -> f v | None -> None
  member x.Return(v) = Some(v)

let maybe = new MaybeMonad()

let rec productNameByID() = maybe {
  let! id = tryReadNumber()
  let! prod = db.TryFindProduct(id)
  return prod.Name }
Run Code Online (Sandbox Code Playgroud)

添加剂monads(又名MonadPlusHaskell)是两者的组合.它有点像monadic计算,可以产生多个值.一个常见的例子是list(或sequence),它可以同时实现bindcombine:

type ListMonadPlus() =
  member x.Zero() = []
  member x.Yield(v) = [v]
  member x.Combine(a, b) = a @ b
  member x.Bind(l, f) = l |> List.map f |> List.concat

let list = new ListMonadPlus()

let cities = list {
  yield "York"
  yield "Orleans" }
let moreCities = list {
  let! n = cities
  yield n
  yield "New " + n }

// Creates: [ "York"; "New York"; "Orleans"; "New Orleans" ]
Run Code Online (Sandbox Code Playgroud)

还有一些其他关键字与任何理论创意都不直接对应.在use与资源关键字交易和forwhile可以被用来实现循环.序列/列表理解实际上使用for而不是let!,因为从语法的角度来看这更有意义(并且for通常需要一些序列 - 尽管它可能是例如异步的).


kvb*_*kvb 5

Monad是根据bindunit操作(仅限)定义的.还有其他结构由其他操作定义(例如,在Haskell中,MonadPlus类型类具有zeroplus操作 - 这些对应于ZeroCombine在F#计算表达式中).据我所知,F#的计算构建器在为它们支持的各种操作提供良好语法方面是独一无二的,但大多数操作与monad无关.