小编Gus*_*Gus的帖子

结合F#异步和计算表达式

假设我想Optionasync工作流程中返回一段时间:

let run = 
    async {
        let! x = doAsyncThing
        let! y = doNextAsyncThing x
        match y with
        | None -> return None
        | Some z -> return Some <| f z
    }
Run Code Online (Sandbox Code Playgroud)

理想情况下,我会使用FSharpx中的可能计算表达式同时作为异步来避免这样做match.我可以创建一个自定义构建器,但是有没有办法一般地组合两个计算表达式?它可能看起来像这样:

let run = 
    async {
        let! x = doAsyncThing
        let! y = doNextAsyncThing x
        return! f y
    }
Run Code Online (Sandbox Code Playgroud)

monads f# asynchronous monad-transformers computation-expression

16
推荐指数
2
解决办法
2304
查看次数

FSharpPlus divRem - 它是如何工作的?

看看FSharpPlus我正在考虑如何创建一个用于的泛型函数

let qr0  = divRem 7  3
let qr1  = divRem 7I 3I
let qr2  = divRem 7. 3.
Run Code Online (Sandbox Code Playgroud)

并提出了一个可能的(工作)解决方案

let inline divRem (D:^T) (d:^T): ^T * ^T = let q = D / d in q,  D - q * d
Run Code Online (Sandbox Code Playgroud)

然后我看了FSharpPlus如何实现它,我发现:

open System.Runtime.InteropServices

type Default6 = class end
type Default5 = class inherit Default6 end
type Default4 = class inherit Default5 end
type Default3 = class inherit Default4 end
type Default2 = class inherit Default3 end …
Run Code Online (Sandbox Code Playgroud)

generics f# constraints f#+

12
推荐指数
2
解决办法
410
查看次数

f#类型成员中的静态解析类型

我想IEnumerable<KeyValuePair<DateTime, 'T>>在我自己的类中实现并向该类添加数学运算符,以便运算符可以像任何数值类型的内联函数一样工作'T- 自动添加约束.

我只是无法使下面的代码工作.在成员声明中,它既不能使用也不能使用'inline'关键字.

另外,如果我定义一个函数

let inline add l r = l + r 
Run Code Online (Sandbox Code Playgroud)

在类型之前使用它而不是添加l.Value + r.Value,它也不起作用.

有人可以告诉我我做错了什么吗?

可能整个方法都是错误的,并且有另一种方法可以实现相同的目标吗?

namespace Test

open System
open System.Linq
open System.Collections.Generic

[<SerializableAttribute>]
type TimeSeries<'T>(dictionary : IDictionary<DateTime, 'T>) =
    let internalList = new SortedList<DateTime, 'T>(dictionary)
    interface IEnumerable<KeyValuePair<DateTime, 'T>> with
        member this.GetEnumerator() = internalList.GetEnumerator()
        member this.GetEnumerator() : Collections.IEnumerator
             = internalList.GetEnumerator() :> Collections.IEnumerator  
    member private this.sl = internalList
    static member inline (+) (left : TimeSeries<'T>, right : TimeSeries<'T>) =
        let res = 
            query …
Run Code Online (Sandbox Code Playgroud)

f# type-inference

8
推荐指数
1
解决办法
311
查看次数

从数组中去除测量单位

我正在调用外部函数需要float[],但我的数组是float<m>[]。如何从数组中去除度量单位?

我需要类似下面的函数,但这不能编译。我想避免数组的任何迭代或重复,因为float<m>float值是相同的......

let demeasure (arr:float<m>[]): float[] = float[] (arr)
Run Code Online (Sandbox Code Playgroud)

arrays f# units-of-measurement

5
推荐指数
1
解决办法
495
查看次数

F# 类型类持久计数器

绅士们,

过去的程序/确定性程序员与 F# 函数式斗争......

我需要一些计数器来记录程序各个区域的计数。以下代码编译干净并且似乎可以工作,但“ctr”永远不会增加。

任何帮助表示赞赏,伊恩

type Count() as this = 
    let mutable ctr = 0
    do
        printfn "Count:Constructor: %A" ctr
    member this.upctr : int = 
        let ctr  = ctr + 1 
        printfn "inCount.upctr %d" ctr
        ctr

let myCount = new Count()
printfn "MyCtr1 %d" (myCount.upctr)
let fred = myCount.upctr
let fred = myCount.upctr
Run Code Online (Sandbox Code Playgroud)

f# counter class

5
推荐指数
1
解决办法
155
查看次数

任何地方都有 option&lt;&gt; 计算表达式吗?

我傻吗?有些东西在 monad/计算表达式中看起来更好,我有很多使用 seq 计算表达式的代码,但是每次我点击一个选项<>我都必须恢复到“Option.map”等。

有点刺耳(当我在 C# 中执行此操作时,我为 IMaybe<> 类型编写了一个 linq 运算符,它看起来不错且一致)。

我可以,但不是特别想写一个,那里肯定有一个(或多个),人们使用哪个?

IE

所以而不是

let postCodeMaybe = 
    personMaybe 
    |> Option.bind (fun p -> p.AddressMaybe())
    |> Option.map (fun -> p.Postcode())
Run Code Online (Sandbox Code Playgroud)

我们可以去

let postCodeMaybe = 
    option {
        for p in personMaybe do
            for a in p.AddressMaybe() do
                 a.Postcode()
    }
Run Code Online (Sandbox Code Playgroud)

我对前面的代码没有任何问题,除了在我的上下文中它存在于许多看起来像后者的“seq”计算表达式中(并且一些将查看此代码的开发人员将来自 C#/LINQ 背景,这些背景基本上是后者)。

f#

5
推荐指数
1
解决办法
445
查看次数

为什么ContT不处理内部monad?

绑定策略ContT忽略内部monad,实际上代码与for相同Cont.

按照其他Monad变形金刚的比喻,我会以这种方式实现它:

return x = ContT ($ (return x))
(>>=) x f = ContT (\k -> runContT x ((=<<) (\a -> runContT (f a) k)))
Run Code Online (Sandbox Code Playgroud)

然后例如这个表达式:

do 
    x1 <- ContT (\k -> k [1, 2])
    x2 <- ContT (\k -> k [10, 20])
    return ((+) x1 x2) 
Run Code Online (Sandbox Code Playgroud)

会导致 [11, 21, 12, 22]

我的问题是设计决策背后的原因是什么?为什么它以这种方式实现,这使得它与其他Monad Transformers非常不同,请注意functor实例是:

fmap f m = ContT $ \c -> runContT m (c . f)
Run Code Online (Sandbox Code Playgroud)

而不是:

fmap f m = ContT $ runCont $ …
Run Code Online (Sandbox Code Playgroud)

haskell monad-transformers

4
推荐指数
1
解决办法
278
查看次数

用bind构成世界范围的异步函数

我有一个运行良好的示例铁路管道:

open FSharpPlus

let funA n =
    if n < 10 then Ok n
    else Error "not less than 10"

let funB n =
    if n < 5 then Ok (n, n * 2)
    else Error "not less than 5"

let funC n = // int -> Result<(int * int), string>
    n
    |> funA
    >>= funB // it works
Run Code Online (Sandbox Code Playgroud)

但是,当我想将其funB转换为异步功能时,出现了编译错误。从逻辑上讲,它应该没有什么不同。相同的输出/输入...怎么了?

应该做些什么才能使其正常工作?

open FSharpPlus

let funA n =
    if n < 10 then Ok n
    else Error "not less …
Run Code Online (Sandbox Code Playgroud)

f# monad-transformers f#+

4
推荐指数
1
解决办法
127
查看次数

如何在F#中组合状态和延续monad

我正在尝试使用任务并行库对树进行求和,其中只生成子任务,直到遍历树直到某个深度,否则它使用延续传递样式对剩余的子节点求和,以避免堆栈溢出.

但是,代码看起来很丑陋 - 使用状态monad来承载当前深度会很好,但状态monad不是尾递归.或者,我如何修改继续monad来携带状态?或者创建状态和延续monad的组合?

let sumTreeParallelDepthCont tree cont = 
  let rec sumRec tree depth cont =
    let newDepth = depth - 1
    match tree with
    | Leaf(num) -> cont num
    | Branch(left, right) ->
      if depth <= 0 then
        sumTreeContMonad left (fun leftM ->
          sumTreeContMonad right (fun rightM ->
            cont (leftM + rightM )))
      else 
        let leftTask = Task.Factory.StartNew(fun () -> 
              let leftResult = ref 0
              sumRec left newDepth (fun leftM -> 
                leftResult := leftM)
              !leftResult
              )
        let rightTask = …
Run Code Online (Sandbox Code Playgroud)

monads f# state monad-transformers continuation

3
推荐指数
1
解决办法
483
查看次数

使用 FSharpPlus 的 Reader monad 转换器示例

我试图理解读者单子转换器。我正在使用FSharpPlus并尝试编译以下示例,该示例首先从阅读器环境中读取某些内容,然后执行一些异步计算,最后合并两个结果:

open FSharpPlus
open FSharpPlus.Data

let sampleReader = monad {
    let! value = ask
    return value * 2
}

let sampleWorkflow = monad {
    do! Async.Sleep 5000
    return 4
}

let doWork = monad {
    let! envValue = sampleReader
    let! workValue = liftAsync sampleWorkflow
    return envValue + workValue
}

ReaderT.run doWork 3 |> Async.RunSynchronously |> printfn "Result: %d"
Run Code Online (Sandbox Code Playgroud)

有了这个,我在它显示的行出现编译错误,let! value = ask并显示以下完全无用的(至少对我来说)错误消息:

将默认类型“obj”应用于类型推断变量时,类型约束不匹配。没有与方法“op_GreaterGreaterEquals”匹配的重载。

已知返回类型:异步

已知类型参数:< obj , (int -> Async) >

感觉就像我只是在某个地方缺少一些操作员,但我无法弄清楚。

f# monad-transformers f#+

3
推荐指数
1
解决办法
718
查看次数

使用"bind"与异步函数

假设我有一些返回的函数Async<Result<string>>:

let getData id = async {
   return Ok (string id)
}
Run Code Online (Sandbox Code Playgroud)

现在,此函数的输入是另一个返回函数的结果Result<int>.

我正在努力研究如何Result.bind在异步CE内部组合2 .

例如:

let main = async {
    let id = Ok 123
    let! x = id |> Result.bind getData

    return x
}
Run Code Online (Sandbox Code Playgroud)

这不起作用,我收到错误:

error FS0001: Type mismatch. Expecting a
    'Result<int,'a> -> Async<'b>'    
but given a
    'Result<int,'a> -> Result<'c,'a>'   
Run Code Online (Sandbox Code Playgroud)

或者如果我不使用let!我得到并且只是使用let

error FS0001: Type mismatch. Expecting a
    'int -> Result<'a,'b>'    
but given a
    'int -> Async<Result<string,'c>>
Run Code Online (Sandbox Code Playgroud)

我见过一些答案是说没有使用Result<'a>,只是让异步异常处理做了艰苦的工作,但我面对同样的问题 …

f# monad-transformers

2
推荐指数
1
解决办法
341
查看次数

尝试了解函子在 FSharpPlus 中是如何实现的

有人可以解释一下这段代码在 F# 中的工作原理吗:

https://github.com/fsprojects/FSharpPlus/blob/master/src/FSharpPlus/Control/Functor.fs#L99-99

static member inline Invoke (mapping: 'T->'U) (source: '``Functor<'T>``) : '``Functor<'U>`` = 
    let inline call (mthd: ^M, source: ^I, _output: ^R) = ((^M or ^I or ^R) : (static member Map : (_*_)*_ -> _) (source, mapping), mthd)
    call (Unchecked.defaultof<Map>, source, Unchecked.defaultof<'``Functor<'U>``>)
Run Code Online (Sandbox Code Playgroud)

具体来说call,该函数使用了我不理解的语法

例如

  • 这是什么(^M or ^I or ^R)意思?
  • 其中哪些部分是代码,哪些部分是类型定义?
  • ... -> 'a当它似乎返回一个元组时,它如何具有类型签名?
  • 是否存在某种类型级别的编程黑客行为?

f# f#+

2
推荐指数
1
解决办法
204
查看次数