小编Aar*_*ach的帖子

歧视联盟 - 允许模式匹配但限制建设

我有一个F#Discriminated Union,我想在构造union case的过程中使用一些"构造函数逻辑".让我们说联盟看起来像这样:

type ValidValue =
| ValidInt of int
| ValidString of string
// other cases, etc.
Run Code Online (Sandbox Code Playgroud)

现在,我想对实际传入的值应用一些逻辑,以确保它们有效.为了确保我不会最终处理ValidValue那些不是真正有效的实例(尚未使用验证逻辑构造),我将构造函数设为私有,并公开一个强制构造它们的逻辑的公共函数.

type ValidValue = 
    private
    | ValidInt of int
    | ValidString of string

module ValidValue =
    let createInt value =
        if value > 0 // Here's some validation logic
        then Ok <| ValidInt value
        else Error "Integer values must be positive"

    let createString value =
        if value |> String.length > 0 // More validation logic
        then Ok <| ValidString value …
Run Code Online (Sandbox Code Playgroud)

f# pattern-matching discriminated-union

10
推荐指数
1
解决办法
281
查看次数

Asyncs之间的无锁信号方式

我正在寻找一种无锁的方式来Async在F#中的两个s 之间发出信号.我有两个尾递归async函数,我想要一个产生,直到另一个信号发出,然后继续下一个递归.我可以使用一个事件,但看起来.NET事件在内部使用锁.到目前为止,我发现的唯一解决方案是使用来自ntdll.dll的键控事件,但我更喜欢不需要直接引用特定于平台的DLL的解决方案.有什么方法可以使用System.Threading.Interlocked或其他.NET技术来实现这一目标吗?

这是我想要实现的一个简单示例:

let rec loop1 () =
    async {
        // do work
        // somehow signal loop2
        return! loop1 ()
    }

let rec loop2 state = 
    async {
        // wait for signal from loop1
        // do work
        return! loop2 state  // This would actually be a new state, not the old state
    }
Run Code Online (Sandbox Code Playgroud)

.net f# lock-free

9
推荐指数
1
解决办法
152
查看次数

F#Erased Type Provider中派生提供的类型的实例类型不正确

我正在研究几个F#类型提供程序来替换一些半生不熟的代码生成,并且我遇到了一些扩展基类型的提供类型的问题.例如,其中一个提供者是实体框架提供者,其中数据库模式的元数据来自外部源,我提供了一种使用DbContext作为其基本类型的类型.该类型具有访问各种DbSet <'table>成员的属性,但是当我尝试访问这些属性时,我收到错误Incorrect instance type. Parameter name: obj.

我相信这是由于'this'参数(所提供属性的GetterCode和SetterCode中的第一个参数)实际上是DbContext类型,而不是我提供的派生类型.这是有道理的,因为我的上下文类型的ProvideConstructor正在调用DbContext构造函数,但我不确定它还能做什么.我只能猜测我误解了关于如何创建类型的东西.我的类型定义,构造函数和属性的代码如下.如果我做错了,请告诉我.

let contextType = ProvidedTypeDefinition("MyContext", Some typeof<DbContext>)
let dbContextCtor = typeof<DbContext>.GetConstructor([|typeof<string>|])

let defaultCtor = // Use static parameter 'sqlConnection'
    ProvidedConstructor(List.Empty, 
        BaseConstructorCall = (fun args -> dbContextCtor, args), 
        InvokeCode = fun args -> Expr.NewObject(dbContextCtor, [ <@@ sqlConnection @@> ]))
let stringCtor = 
    ProvidedConstructor([ProvidedParameter("sqlConnection", typeof<string>)], 
        BaseConstructorCall = (fun args -> dbContextCtor, args), 
        InvokeCode = fun args -> Expr.NewObject(dbContextCtor, [ args.[1] ]))

contextType.AddMember(defaultCtor)
contextType.AddMember(stringCtor)
Run Code Online (Sandbox Code Playgroud)

...

// Add a DbSet field and property for each …
Run Code Online (Sandbox Code Playgroud)

f# entity-framework type-providers

8
推荐指数
0
解决办法
134
查看次数

F#通用单元在参数中相互定义

在定义具有参数的运算符时,我遇到了F#测量单位的问题,该参数具有根据来自另一个参数的通用测量单位定义的通用测量单位.例如:

type Quotient<[<Measure>]'b> =
| Divisible of int64<'b>
| Remaindered of int64<'b> * int64<'b>

let (|/) (x: int64<'a>) (y: int64<'a/'b>) =
    let q = x / y
    if q * y = x then Divisible q else Remaindered (q, x - (q * y))  
Run Code Online (Sandbox Code Playgroud)

这里,y定义在<'a/'b>,其中<'a>是单位x.我期待的类型(|/)int64<'a> -> int64<'a/'b> -> Quotient<'b>,但编译器告诉我类型是x:int64<'b> -> y:int64 -> Quotient<'b>.

我想将此用于类型转换,其中十进制数是不可能的.我的目标是创建用于处理Quotients的运算符,而不是将逻辑用于计算每个类型转换中的余数.是否有可能实现这一目标,还是应该以不同的方式进行类型转换?

generics f# units-of-measurement .net-4.6

6
推荐指数
1
解决办法
97
查看次数

如何创建使用不同传输的单个NServiceBus端点?

背景

我们正在尝试在我们公司引入一种新的架构模式,并正在考虑使用服务总线进行事件采购的CQRS.我们目前正在开发的POC技术有NServiceBus,Event Store和MSMQ.我们希望在NServiceBus中使用两个不同的传输定义一个端点,我们的命令使用MSMQ,事件使用Event Store.我们企业的当前状态不允许我们现在轻松地将所有内容切换到Event Store,因为我们使用MSMQ对我们的遗留应用程序进行了大量投资,这是我们考虑混合方法的原因.

是否可以创建使用不同传输的单个NServiceBus端点?如果有,怎么样?如果不是,有哪些替代方案?

msmq nservicebus cqrs event-sourcing get-event-store

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

自定义计时器分辨率与System.Timers.Timer分辨率

我们需要一个定时器,它在给定的时间间隔内触发一段时间,然后停止,我们想要异步等待定时器停止.当然,这可以通过课程来完成System.Timers.Timer,但它有点麻烦,涉及使用AutoResetEvent或类似.为了简化这个用例,我创建了一个自定义计时器类.作为一个F#项目,我使我的计时器不可变并基于代理,但我也希望与.NET计时器的实现方式保持一致.我看了一下System.Timers.Timer参考源,它好像是换行的System.Threading.Timer,它使用的是Win32 QueryUnbiasedInterruptTimeAPI.因此,我在创建计时器时使用相同的API来管理计时器间隔.但是,我System.Timers.Timer在测试时观察计时器和计时器之间的不同行为.

当我的自定义计时器使用1ms间隔和100ms超时时,计时器将触发约65次,每次事件之间约1.5ms.当使用System.Timers.Timer1ms间隔并在经过100ms后停止定时器(使用a System.Diagnostics.Stopwatch来检查经过的时间)时,定时器仅在每次事件之间大约15ms发射7次.这似乎更像System.Timers.Timer是使用DateTime.Ticks然后QueryUnbiasedInterruptTime.我的自定义计时器比内置计时器具有更高的分辨率,我可能会遇到哪些问题System.Timers.Timer?我期待一致的行为,并惊讶地发现它们如此不同.

我还担心我必须添加到我的函数中以计算下一个间隔的特定行.我看到Elapsed每个经过的时间间隔发生两次事件而不是一次,原因是过去的时间比间隔少了一毫秒,所以它基本上将下一个间隔计算为零毫秒并立即激发.我通过添加一个小于一毫秒的下一个间隔的检查并替换整个间隔来纠正这个,但这感觉就像一个黑客.我在代码中注释了这一行.

我的自定义计时器的代码如下:

open System

module private Timer =
    open System.Runtime.InteropServices
    open System.Runtime.Versioning

    [<DllImport("kernel32.dll")>]
    [<ResourceExposure(ResourceScope.None)>]
    extern bool QueryUnbiasedInterruptTime (int64& value)

    let inline private queryUnbiasedInterruptTime () =
        let mutable ticks = 0L
        if QueryUnbiasedInterruptTime &ticks
        then Some ticks
        else None

    /// Get the current timestamp in 100-ns increments 
    let getTicks () =
        match queryUnbiasedInterruptTime() …
Run Code Online (Sandbox Code Playgroud)

.net f# timer immutability

5
推荐指数
0
解决办法
180
查看次数