玩弄F#类型和迷路

玩弄F#类型和迷路,f#,c#-to-f#,f#-3.0,f#-scripting,F#,C# To F#,F# 3.0,F# Scripting,我一直在读一些关于F#的书,并决定试一试。我从一个有点复杂的例子开始,我想到了,然后马上就迷路了。我想知道是否有人可以分享一些想法 我想写一个名为ComparisonStrategy的方法。它接受长度可变的比较,其操作方式可以是: 一个类型为('T->*)的函数,它是一种选择单个字段进行比较的方法 两元组的('T->'U,IEqualityComparer'U) |与('T->'U)*IEqualityComparer阵列的比较= 平等比较人(姓名); 比较((fun(p:Person)->p.

我一直在读一些关于F#的书,并决定试一试。我从一个有点复杂的例子开始,我想到了,然后马上就迷路了。我想知道是否有人可以分享一些想法

我想写一个名为
ComparisonStrategy
的方法。它接受长度可变的
比较,其操作方式可以是:

  • 一个类型为
    ('T->*)
    的函数,它是一种选择单个字段进行比较的方法
  • 两元组的
    ('T->'U,IEqualityComparer'U)
    |与('T->'U)*IEqualityComparer阵列的比较=
    平等比较人(姓名);
    比较((fun(p:Person)->p.ID),EqualityComparer.Default)|]//此处出错
    
    从另一个角度来看问题,您似乎希望能够构造以两种不同方式(您指定的)执行比较的对象,然后组合它们

    让我们先看看构建执行比较的对象的两种方法。您可以通过
    IEqualityComparer Something
    来表示两者,并对结果执行比较。您可以定义如下函数:

    /// Creates a comparer for 'T values based on a predicate that 
    /// selects some value 'U from any 'T value (e.g. a field)
    let standardComparer (f:'T -> 'U) = 
      { new IEqualityComparer<'T> with
          member x.Equals(a, b) = 
            (f a).Equals(b)  // Call 'f' on the value & test equality of results
          member x.GetHashCode(a) = 
            (f a).GetHashCode() } // Call 'f' and get hash code of the result
    
    /// Creates a new IEqualityComparer that is based on two other comparers
    /// Two objects are equal if they are equal using both comparers.
    let combineComparers (comp1:IEqualityComparer<'T>) (comp2:IEqualityComparer<'T>) =
      { new IEqualityComparer<'T> with
          member x.Equals(a, b) =
            comp1.Equals(a, b) && comp2.Equals(a, b) // Combine results using &&
          member x.GetHashCode(a) =
            // Get hash code of a tuple composed by two hash codes
            hash (comp1.GetHashCode(a), comp2.GetHashCode(a)) }
    
    // Create a list of primitive comparers that compare 
    // Name, Age and ID using special 'idComparer'
    let comparers =
      [ standardComparer (fun (p:Person) -> p.Name);
        standardComparer (fun (p:Person) -> p.Age);
        equalityComparer (fun (p:Person) -> p.ID) idComparer ]
    
    // Create a single comparer that combines all of them...
    let comparePerson = comparers |> Seq.reduce combineComparers
    
    现在你说你想用上面两种方法中的一种来建立一个单一的比较策略。我不完全明白你的意思。当所有指定的比较器报告两个对象相等时,是否希望它们相等


    假设是这样的话,您可以编写一个结合两个
    IEqualityComparerIt的函数,如果您可以显示您尝试过的代码,那么它会很有帮助。无论如何,函数类型('T->*)看起来像是不能用F#表示的东西。@wmeyer我认为OP的意思是
    'T->'u
    ,而不是
    'T->*
    ,类似于
    map
    “我想知道是否有人可以分享一些想法”。我的第一个想法是你在深水区潜入。F#type系统主要是关于ML类型(元组、记录和联合),其中等式、比较、哈希和打印函数都是为您自动生成的。当默认语义不是您想要的时,您可以使用
    *By
    *With
    函数,并传入一个执行所需操作的函数。你所做的很少有用。谢谢,这不是我想要的。我正在努力实现以下两个目标。找到一种通用的方法为每个对象生成一个相等的方法。@user1763590我不太确定我是否理解您的目标。你能给你的问题加一个例子来澄清这一点吗?您可以在对象内部使用
    standardcomarer
    equalityComparer
    来定义其
    Equals
    GetHashCode
    方法。。。虽然如果你只是从F#开始,那么这可能不是最好的探索领域,因为这是一个相当复杂的例子。。。
    /// Creates a new IEqualityComparer that is based on two other comparers
    /// Two objects are equal if they are equal using both comparers.
    let combineComparers (comp1:IEqualityComparer<'T>) (comp2:IEqualityComparer<'T>) =
      { new IEqualityComparer<'T> with
          member x.Equals(a, b) =
            comp1.Equals(a, b) && comp2.Equals(a, b) // Combine results using &&
          member x.GetHashCode(a) =
            // Get hash code of a tuple composed by two hash codes
            hash (comp1.GetHashCode(a), comp2.GetHashCode(a)) }
    
    // Create a list of primitive comparers that compare 
    // Name, Age and ID using special 'idComparer'
    let comparers =
      [ standardComparer (fun (p:Person) -> p.Name);
        standardComparer (fun (p:Person) -> p.Age);
        equalityComparer (fun (p:Person) -> p.ID) idComparer ]
    
    // Create a single comparer that combines all of them...
    let comparePerson = comparers |> Seq.reduce combineComparers