在F#中,我可以在不定义类的情况下表示受限类型吗?假设我想表示第一个除以第二个数字的所有数字对.
在C#我能做到:
class PairDivides
{
int a {get;private set;}
int b {get;private set;}
PairDivides(int first, int second)
{
if (a % b != 0)
{
throw new Exception();
}
this.a = first;
this.b = second;
}
}
Run Code Online (Sandbox Code Playgroud)
现在创建一个不分割的PairDivides
实例b
是不可能的a
......
这可以在F#中仅使用功能构造(记录,区分联合,可能是活动模式等)来完成吗?
我希望能够创建和接收类似这些对的东西,确保它们构造正确.
我是F#和.Net世界的初学者,我正在尝试使此F#脚本起作用:
#r "./packages/SQLProvider/lib/netstandard2.0/FSharp.Data.SqlProvider.dll"
#r "./packages/SQLProvider/lib/netstandard2.0/netstandard.dll"
#r "./packages/Npgsql/lib/netstandard2.0/Npgsql.dll"
open FSharp.Data.Sql
open Npgsql
let [<Literal>] ConnString =
"Host=localhost;" +
"Port=5431;" +
"Database=suavetododb;" +
"Username=postgres;" +
"Password=postgres"
let [<Literal>] DbVendor = Common.DatabaseProviderTypes.POSTGRESQL
let [<Literal>] ResPath = @"./packages/Npgsql/lib/netstandard2.0"
type Sql =
SqlDataProvider<
DbVendor,
ConnString,
"",
ResPath,
1000,
true>
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误:
错误FS3033:类型提供程序'FSharp.Data.Sql.SqlTypeProvider'报告了一个错误:由于以下原因,无法解析字段令牌0x04000523:无法加载字段'Npgsql.NpgsqlConnection + d__28:<> u__2'(7)到:无法加载文件或程序集'System.Threading.Tasks.Extensions,版本= 4.1.0.0,区域性=中性,PublicKeyToken = cc7b13ffcd2ddd51'或其依赖项之一。程序集:System.Threading.Tasks.Extensions,版本= 4.1.0.0,文化=中性,PublicKeyToken = cc7b13ffcd2ddd51类型:成员:(null)签名:程序集:(my_filesystem)/API/packages/Npgsql/lib/netstandard2.0/ Npgsql.dll类型:d__28成员:(空)签名:
这很奇怪,因为Npgsql
实际上是导入的(所以最后一个#r
实际上有效)。
该数据库是通过docker启动的:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4704763ec2ba suave_rezoom_db:0.1 "docker-entrypoint.s…" 25 hours ago Up …
Run Code Online (Sandbox Code Playgroud) 这是我用来解释我的问题的最小代码示例.以下代码组织在两个文件中并编译正常:
DataStruct.fs
module MyMod
type XXX = {
a: int
}
with
static member GetNew =
{
a = -1
}
type YYY = {
a: float
}
with
static member GetNew =
{
a = -1.0
}
type Choice =
| XXX of XXX
| YYY of YYY
Run Code Online (Sandbox Code Playgroud)
Program.fs
open MyMod
let generator =
let res = XXX.GetNew
Choice.XXX res
let myVal : XXX =
match generator with
| XXX x -> x
| _ -> printfn "expected XXX, …
Run Code Online (Sandbox Code Playgroud) 为什么这有效:
type Money =
{ Amount : decimal } with
member inline m.gotMoney : bool =
m.Amount > 0M
Run Code Online (Sandbox Code Playgroud)
但这并不
type MoneyUOM<[<Measure>]'currency> =
{ Amount : decimal<'currency> } with
member inline m.gotMoney : bool =
m.Amount > 0M<_>
Run Code Online (Sandbox Code Playgroud)
相反,我得到error FS0339: The signature and implementation are not compatible because the type parameter in the class/signature has a different compile-time requirement to the one in the member/implementation
使用 Visual Studio 2015 Update 3 和fsi.exe
F# v4.0,我尝试运行此脚本:
//error.fsx
#if INTERACTIVE
let msg = "Interactive"
#else
let msg = "Not Interactive"
#endif
let add x y =
x + y
printfn "%d" (add 1 2)
Run Code Online (Sandbox Code Playgroud)
输出: error.fsx(12,15):错误 FS0039:未定义值或构造函数“add”
如果我然后注释掉#if
- #else
-#endif
块,它工作正常:
// fixed.fsx
//#if INTERACTIVE
// let msg = "Interactive"
//#else
// let msg = "Not Interactive"
//#endif
let add x y =
x + y
printfn "%d" (add 1 2)
Run Code Online (Sandbox Code Playgroud)
输出: 3
我确定我做错了什么(而不是这是一个错误),但我一生都无法弄清楚如何进行这项工作。 …