【问题标题】:What am I doing wrong with Set.Fold F#Set.Fold F#我做错了什么
【发布时间】:2016-05-18 12:14:20
【问题描述】:

着色问题:

您好,我正在尝试实现一个 bool 函数,当颜色可以扩展到一个国家/地区时返回 true,否则返回 false,但是我在使用集合时遇到了问题,因为我们无法对它们进行模式匹配...

我的代码:

type Country = string;;
type Chart = Set<Country*Country>;;
type Colour = Set<Country>;;
type Colouring = Set<Colour>;;

(* This is how you tell that two countries are neghbours.  It requires a chart.*)
let areNeighbours ct1 ct2 chart =
  Set.contains (ct1,ct2) chart || Set.contains (ct2,ct1) chart;;
(* val areNeighbours :
  ct1:'a -> ct2:'a -> chart:Set<'a * 'a> -> bool when 'a : comparison
  *)

(* The colour col can be extended by the country ct when they are no neighbours
according to chart.*)

let canBeExtBy (col:Colouring) (ct:Country) (chart:Chart) = col |> Set.fold (fun x -> (if (areNeighbours x ct chart) then true else false))

预期结果:根据图表中定义的邻域,我们需要检查 ct 是否是 col 中任何国家的邻居(假设 col 中有国家)。 所以如果

chart = set
    [("Andorra", "Benin"); ("Andorra", "Canada"); ("Andorra", "Denmark");
     ("Benin", "Canada"); ("Benin", "Denmark"); ("Canada", "Denmark");
     ("Estonia", "Canada"); ("Estonia", "Denmark"); ("Estonia", "Finland");
     ...]

还有

col = set 
    ["Andorra"]

那么当ct = "Benin" or "Canada" or "Denmark" etc... 安道尔与这些国家接壤时,canBeExt 应该返回 false,因此它们的颜色不能与安道尔相同。

显然我在 canBeExtBy 中有一个类型错误,因为我试图返回一个 bool 并且它期待 'a:Colouring. 我不知道如何实现它..

感谢您的帮助!

【问题讨论】:

  • canBeExtBy 应该返回哪个值(什么类型)?你能提供一些预期的测试用例,以及它们的预期返回值吗?
  • 传递给Set.fold的函数的类型应该是'State -&gt; 'T -&gt; 'State。这意味着 两个(咖喱)函数参数,但您的匿名函数只接受一个参数。
  • 您可以将(if (areNeighbours x ct chart) then true else false) 缩短为areNeighbours x ct chart

标签: function f# functional-programming set


【解决方案1】:

检查集合中的任何元素是否满足给定条件:这不是 fold 的工作,但是,通过适当的否定,对于 existsforall。 任一个

    let fornone f = Set.forall (f >> not)
    let doesnotexist f = Set.exists f >> not

可以,如FuleSnabel的回答所示。但是,当然可以从 fold 构建这些函数,尽管除了作为柯里化、函数组合和无点样式的说明之外,没有人会这样做。

    let fornone f = Set.fold (fun s -> f >> not >> (&&) s) true
    let doesnotexist f = Set.fold (fun s -> f >> (||) s) false >> not

【讨论】:

    【解决方案2】:

    这个怎么样?

    type Country      = string
    type Neighbours   = Set<Country*Country>
    type SharesColour = Set<Country>
    
    let areNeighbours (ns : Neighbours) (ct1 : Country) (ct2 : Country) : bool =
      Set.contains (ct1,ct2) ns || Set.contains (ct2,ct1) ns
    
    let canShareColour (ns : Neighbours) (ct : Country) (s : SharesColour) : bool =
      s |> Seq.exists (areNeighbours ns ct) |> not
    
    let neighbours : Neighbours = 
      set [| 
        ("Andorra", "Benin")  ; ("Andorra", "Canada") ; ("Andorra", "Denmark");
        ("Benin"  , "Canada") ; ("Benin"  , "Denmark"); ("Canada" , "Denmark");
        ("Estonia", "Canada") ; ("Estonia", "Denmark"); ("Estonia", "Finland");
      |]
    
    let sharesColour : SharesColour =
      set [|
        "Andorra"
      |]
    
    [<EntryPoint>]
    let main argv =
      printfn "%A" <| canShareColour neighbours "Estonia" sharesColour
      printfn "%A" <| canShareColour neighbours "Benin"   sharesColour
      0
    

    将名称更改为对我更有意义的名称。你可能不同意。

    【讨论】:

      猜你喜欢
      • 2011-06-01
      • 1970-01-01
      • 2021-04-14
      • 2021-04-19
      • 2017-03-13
      • 2017-01-18
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多