【问题标题】:How do I implement this generic C# interface using F#?如何使用 F# 实现这个通用 C# 接口?
【发布时间】:2020-07-30 18:24:15
【问题描述】:

我想在 F# 中用this interface 创建一个对象:

namespace JWT
{
    /// <summary>
    /// Provides JSON Serialize and Deserialize.  Allows custom serializers used.
    /// </summary>
    public interface IJsonSerializer
    {
        /// <summary>
        /// Serialize an object to JSON string
        /// </summary>
        /// <param name="obj">object</param>
        /// <returns>JSON string</returns>
        string Serialize(object obj);

        /// <summary>
        /// Deserialize a JSON string to typed object.
        /// </summary>
        /// <typeparam name="T">type of object</typeparam>
        /// <param name="json">JSON string</param>
        /// <returns>Strongly-typed object</returns>
        T Deserialize<T>(string json);
    }
}

我尝试过使用对象表达式,但通用的 Deserialize 方法让我感到困惑:

  let serializer =
    {
      new JWT.IJsonSerializer
        with
          member this.Serialize (o : obj) =
            failwith "Not implemented"

          member this.Deserialize (json : string) =
            let decoded : Result<'t, string> = 
              Decode.fromString payloadDecoder json

            match decoded with
            | Result.Ok (o : 't) ->
              o
            | Result.Error error ->
              failwith error
    }

错误是:

此代码不够通用。类型变量 'a 无法泛化,因为它会超出其范围

我该如何实施?


$ dotnet --version
3.1.300

【问题讨论】:

  • Decode.fromString 的签名是什么?
  • Decode.fromString 来自Thoth.Json string -&gt; Decoder&lt;'t&gt; -&gt; Result&lt;'t, string&gt;
  • 奇怪,这在我的环境中不会发生,我使用的是 F# Core 4.7.2,你的是什么?

标签: f# c#-to-f#


【解决方案1】:

我们可以通过注释成员来处理这个错误。这样,类型系统将有足够的信息来完全识别正在发生的事情。

如果我稍微调整一下你的代码,我就能编译它:

open Thoth.Json

type IJsonSerializer =
  abstract member Serialize : o:obj -> string
  abstract member Deserialize<'a> : json:string -> 'a

type Json () =
    let payloadDecoder : Decoder<'a> = 
        fun _ -> failwith "not impl."

    interface IJsonSerializer with
        member this.Serialize (o : obj) : string =
            failwith "not impl."

        member this.Deserialize<'a> (json : string) : 'a =
            match Decode.fromString payloadDecoder json with
            | Ok (o : 'a) -> o
            | Error error -> failwith error

通过完全注释Deserialize 成员,现在应该满足类型系统。

需要注意的几点:

  • 我包含了IJsonSerializer 接口的 F# 版本,因此我的代码可以编译。虽然这对您的最终结果不是必需的。
  • 我为payloadDecoder 包含了一个存根,因为您没有将它包含在您的问题中。因此,即使这段代码可以编译,它实际上也不会工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 2021-02-03
    • 1970-01-01
    相关资源
    最近更新 更多