首页 > 解决方案 > F# 类型约束错误尝试编写类型映射

问题描述

我正在尝试在 C# 库之上编写 API。C# 代码有一个从类型到值的字典,我想用不可变的数据结构来表示。

但是,我无法正确编写类型约束:

open System

// System.Type cannot be used a map key
// TODO: Is this enough data to form a key?
type ComparableType = 
  {
    AssemblyQualifiedName : string
  }

type TypeMap<'t> = 
  private 
  | TypeMap of Map<ComparableType, 't>

module TypeMap = 

  let private innerMap = 
    function
    | TypeMap m -> m
  
  let empty () = 
    TypeMap Map.empty

  // Here is the problem line!  
  let add<'t, 'v when 'v :> 't> (v : 'v) (m : TypeMap<'t>) =        
    let t = typeof<'v>

    let k = 
      {
        AssemblyQualifiedName = t.AssemblyQualifiedName
      }

    m
    |> innerMap
    |> Map.add k (v :> 't)
    |> TypeMap

错误:

无效约束:用于约束的类型是密封的,这意味着约束只能由最多一种解决方案满足

标签: f#

解决方案


我不认为 F# 可以处理这样的通用约束。此外,它不会让您对未确定的类型进行强制处理。你最好的选择是使用box v而不是(v :> 't)

像这样:

type ComparableType = 
{
    AssemblyQualifiedName : string
}

type TypeMap = 
private 
| TypeMap of Map<ComparableType, obj>

module TypeMap = 

let private innerMap = 
    function
    | TypeMap m -> m

let empty () = 
    TypeMap Map.empty

let inline add (v : 'v) (m : TypeMap) =        
    let t = typeof< 'v>

    let k = 
    {
        AssemblyQualifiedName = t.AssemblyQualifiedName
    }

    m
    |> innerMap
    |> Map.add k (box v)
    |> TypeMap

let inline get< ^v>  (m : TypeMap) : ^v =
    let t = typeof<'v>

    let k = 
    {
        AssemblyQualifiedName = t.AssemblyQualifiedName
    }

    (innerMap m).[k] 
    |> unbox

推荐阅读