如何在 F# 中使这些函数通用?
how to make these functions generic, in F#?
我有这两个功能:
// load from cache
let private loadFromCacheAsync filespec =
async {
let! bytes = File.ReadAllBytesAsync(filespec) |> Async.AwaitTask
let result =
use pBytes = fixed bytes
let sourceSpan = Span<byte>(NativePtr.toVoidPtr pBytes, bytes.Length)
MemoryMarshal.Cast<byte, ShortTradeData>(sourceSpan).ToArray()
return (result |> Array.map (fun x -> x.ToTradeData()))
}
// save to cache
let private saveToCacheAsync filespec (data: TradeData array) =
Directory.CreateDirectory cacheFolder |> ignore
let sizeStruct = sizeof<ShortTradeData>
let smallData = data |> Array.map ShortTradeData.FromTradeData
use ptr = fixed smallData
let nativeSpan = Span<byte>(NativePtr.toVoidPtr ptr, data.Length * sizeStruct).ToArray()
File.WriteAllBytesAsync(filespec, nativeSpan) |> Async.AwaitTask
我正在努力使它们通用:
// load from cache
let private loadFromCacheAsync<'a> filespec =
async {
let! bytes = File.ReadAllBytesAsync(filespec) |> Async.AwaitTask
let result =
use pBytes = fixed bytes
let sourceSpan = Span<byte>(NativePtr.toVoidPtr pBytes, bytes.Length)
MemoryMarshal.Cast<byte, 'a>(sourceSpan).ToArray()
return result
}
// save to cache
let private saveToCacheAsync<'a> filespec (data: 'a array) =
Directory.CreateDirectory cacheFolder |> ignore
let sizeStruct = sizeof<'a>
use ptr = fixed data
let nativeSpan = Span<byte>(NativePtr.toVoidPtr ptr, data.Length * sizeStruct).ToArray()
File.WriteAllBytesAsync(filespec, nativeSpan) |> Async.AwaitTask
第一个编译失败:
“没有已知的方法 Cast 重载”
第二个编译失败:
“当'a: unmanaged'
时,类型参数缺少约束
所以我可以通过改变函数使第二个编译:
let private saveToCacheAsync<'a when 'a: unmanaged> filespec (data: 'a array) =
但我认为“when 'a: struct”更有意义。阅读文档后,看起来非托管适用于具有原始(非托管)类型的结构......仍然不知道为什么结构不起作用。
但是对于第一个功能,我不知道应该做些什么来修复它。
完整的错误信息是:
DataCache.fs(28, 17): [FS0041] No overloads match for method 'Cast'.
Known type of argument: Span<byte>
Available overloads:
- MemoryMarshal.Cast<'TFrom,'TTo when 'TFrom: (new: unit -> 'TFrom) and 'TFrom: struct and 'TFrom :> ValueType and 'TTo: (new: unit -> 'TTo) and 'TTo: struct and 'TTo :> ValueType>(span: ReadOnlySpan<'TFrom>) : ReadOnlySpan<'TTo>
- MemoryMarshal.Cast<'TFrom,'TTo when 'TFrom: (new: unit -> 'TFrom) and 'TFrom: struct and 'TFrom :> ValueType and 'TTo: (new: unit -> 'TTo) and 'TTo: struct and 'TTo :> ValueType>(span: Span<'TFrom>) : Span<'TTo>
如果我看一下它需要的类型:
- 'TTo 当'TFrom: (new: unit -> 'TFrom)
- 'TFrom: 结构
- 'TFrom :> 值类型
- 'TTo:(新:单位 -> 'TTo)
- 'TTo: 结构
- 'TTo :> 值类型
我们在这里关心TTo:
- 'TTo 当'TFrom: (new: unit -> 'TFrom)
- 'TTo:(新:单位 -> 'TTo)
- 'TTo: 结构
- 'TTo :> 值类型
我还是不明白:看起来它需要是一个结构,并且可以转换为值类型(那么是结构?)并且有一个空的构造函数?第一行没看懂
由于 loadFromCacheAsync
的“from”类型参数始终是 byte
,您只需要对其称为 'a
的“to”参数进行三个约束:
'a: (new: unit -> 'a)
'a: struct
'a :> System.ValueType
最后两个看起来确实多余,但我认为这只是 .NET 基本要求的产物。
loadFromCacheAsync
的最终签名是:
let private loadFromCacheAsync<'a when 'a: (new: unit -> 'a) and 'a: struct and 'a :> ValueType> filespec =
我有这两个功能:
// load from cache
let private loadFromCacheAsync filespec =
async {
let! bytes = File.ReadAllBytesAsync(filespec) |> Async.AwaitTask
let result =
use pBytes = fixed bytes
let sourceSpan = Span<byte>(NativePtr.toVoidPtr pBytes, bytes.Length)
MemoryMarshal.Cast<byte, ShortTradeData>(sourceSpan).ToArray()
return (result |> Array.map (fun x -> x.ToTradeData()))
}
// save to cache
let private saveToCacheAsync filespec (data: TradeData array) =
Directory.CreateDirectory cacheFolder |> ignore
let sizeStruct = sizeof<ShortTradeData>
let smallData = data |> Array.map ShortTradeData.FromTradeData
use ptr = fixed smallData
let nativeSpan = Span<byte>(NativePtr.toVoidPtr ptr, data.Length * sizeStruct).ToArray()
File.WriteAllBytesAsync(filespec, nativeSpan) |> Async.AwaitTask
我正在努力使它们通用:
// load from cache
let private loadFromCacheAsync<'a> filespec =
async {
let! bytes = File.ReadAllBytesAsync(filespec) |> Async.AwaitTask
let result =
use pBytes = fixed bytes
let sourceSpan = Span<byte>(NativePtr.toVoidPtr pBytes, bytes.Length)
MemoryMarshal.Cast<byte, 'a>(sourceSpan).ToArray()
return result
}
// save to cache
let private saveToCacheAsync<'a> filespec (data: 'a array) =
Directory.CreateDirectory cacheFolder |> ignore
let sizeStruct = sizeof<'a>
use ptr = fixed data
let nativeSpan = Span<byte>(NativePtr.toVoidPtr ptr, data.Length * sizeStruct).ToArray()
File.WriteAllBytesAsync(filespec, nativeSpan) |> Async.AwaitTask
第一个编译失败:
“没有已知的方法 Cast 重载”
第二个编译失败:
“当'a: unmanaged'
时,类型参数缺少约束所以我可以通过改变函数使第二个编译:
let private saveToCacheAsync<'a when 'a: unmanaged> filespec (data: 'a array) =
但我认为“when 'a: struct”更有意义。阅读文档后,看起来非托管适用于具有原始(非托管)类型的结构......仍然不知道为什么结构不起作用。
但是对于第一个功能,我不知道应该做些什么来修复它。
完整的错误信息是:
DataCache.fs(28, 17): [FS0041] No overloads match for method 'Cast'.
Known type of argument: Span<byte>
Available overloads:
- MemoryMarshal.Cast<'TFrom,'TTo when 'TFrom: (new: unit -> 'TFrom) and 'TFrom: struct and 'TFrom :> ValueType and 'TTo: (new: unit -> 'TTo) and 'TTo: struct and 'TTo :> ValueType>(span: ReadOnlySpan<'TFrom>) : ReadOnlySpan<'TTo>
- MemoryMarshal.Cast<'TFrom,'TTo when 'TFrom: (new: unit -> 'TFrom) and 'TFrom: struct and 'TFrom :> ValueType and 'TTo: (new: unit -> 'TTo) and 'TTo: struct and 'TTo :> ValueType>(span: Span<'TFrom>) : Span<'TTo>
如果我看一下它需要的类型:
- 'TTo 当'TFrom: (new: unit -> 'TFrom)
- 'TFrom: 结构
- 'TFrom :> 值类型
- 'TTo:(新:单位 -> 'TTo)
- 'TTo: 结构
- 'TTo :> 值类型
我们在这里关心TTo:
- 'TTo 当'TFrom: (new: unit -> 'TFrom)
- 'TTo:(新:单位 -> 'TTo)
- 'TTo: 结构
- 'TTo :> 值类型
我还是不明白:看起来它需要是一个结构,并且可以转换为值类型(那么是结构?)并且有一个空的构造函数?第一行没看懂
由于 loadFromCacheAsync
的“from”类型参数始终是 byte
,您只需要对其称为 'a
的“to”参数进行三个约束:
'a: (new: unit -> 'a)
'a: struct
'a :> System.ValueType
最后两个看起来确实多余,但我认为这只是 .NET 基本要求的产物。
loadFromCacheAsync
的最终签名是:
let private loadFromCacheAsync<'a when 'a: (new: unit -> 'a) and 'a: struct and 'a :> ValueType> filespec =