我正在尝试学习F#,并整理了以下代码:
open System.Collections.Generic
type Version = Version of int
type AggregateId = AggregateId of int
type IEventdata = interface end
type EventMeta = EventMeta of AggregateId * Version
type Event = Event of EventMeta * IEventdata
type ICommandData = interface end
type CommandMeta = CommandMeta of AggregateId * Version
type Command = CommandMeta * ICommandData
type EventStore = {
GetEvents : AggregateId -> Event seq;
Insert : Event seq -> unit
}
let commandDispatcherFactory (mapping: (Command -> Event seq -> Event seq), es: EventStore) =
(
fun (command: Command) ->
match command with
| (CommandMeta(aggregateId, version), commandData) ->
let events = es.GetEvents (aggregateId)
let resultingEvents = mapping command events
(es.Insert(resultingEvents))
)
type DummyCommand =
| Command1
interface ICommandData
type DummyCommand2 =
| Command2
interface ICommandData
type UnsupportedCommand =
| Command3
let dummyMapping = (fun ((command, commandData):Command) (events: Event seq) ->
match commandData with
| :? DummyCommand as dummyCommand ->
(printfn "Handling Command: %A" dummyCommand)
Seq.empty<Event>
| :? DummyCommand2 as dummyCommand ->
(printfn "Handling Command: %A" dummyCommand)
Seq.empty<Event>
| _ ->
(printfn "Unsupported command: %A" commandData)
Seq.empty<Event>
)
let dummyEs = {
GetEvents = (fun (aggregateId) -> Seq.empty<Event>);
Insert = (fun (events:Event seq) -> ())
}
dummyMapping (CommandMeta(AggregateId(1),Version(1)), Command1) Seq.empty<Event>
dummyMapping (CommandMeta(AggregateId(1),Version(1)), Command2) Seq.empty<Event> // Why does this work?
let commandDispatcher = commandDispatcherFactory(dummyMapping, dummyEs)
commandDispatcher (CommandMeta(AggregateId(1),Version(1)), Command1)
commandDispatcher (CommandMeta(AggregateId(1),Version(1)), Command2) // this doesn't work
我知道这可能是一堵文字墙,但是我没有设法缩小文字范围。这是对我的commandDispatcher的最后一次调用不起作用,我不知道为什么。我知道可能还有其他事情可以做得更好,但这是我正在努力的事情:)
这是简化的复制品:
let f x (y:System.IComparable) = ()
let g = f 1
g 3
g "test" // not okay
let g' : System.IComparable -> unit = f 1
g' 3
g' "test" // okay
let g'' x = f 1 x
g'' 3
g'' "test" // okay
发生的是编译器为推断出通用类型g
(g:('a -> unit) when 'a :> System.IComparable
在我的示例中)。但是,它g
是一个语法值,因此不能通用(请参阅有关值限制的问题),因此编译器需要选择一个特定类型。如果您根本不使用g
,则会出现编译器错误。如果仅在一种具体类型上使用它,则编译器将选择该类型。如果您在多种类型上使用它,则编译器将基于所使用的第一种类型进行专业化处理,并在此之后引发错误。
两种解决方法是使用非泛型类型注释或eta-expand,以便这g
不是语法值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句