F # отказывается определять тип на основе нескольких ограничений - PullRequest
0 голосов
/ 20 мая 2019

Я перепробовал все, чтобы компилятор слушал. Однако он отказывается понимать. Я пытаюсь сравнить значения цвета каждого элемента, и если они совпадают, верните true, иначе верните false.

Я поместил ограничения того, что я хочу, и он все еще не может определить тип.

let all_same_color cs =
  let mutable d=true
  let (col:Color) = card_color (cs.Head:Card)
  for i in cs do
    let col=card_color i
    if not (col = col) then
      printfn "Black"
      d<-false
    else
      d<-d
    printfn "Val %b" d
  d

Я ожидаю, что он вернет true, если цвета совпадают, или false, если нет.

В этой строке постоянно появляются ошибки:

let (col:Color) = card_color (cs.Head:Card)

 Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this programpoint to constrain the type of the object. This may allow the lookup to be resolved.

1 Ответ

5 голосов
/ 20 мая 2019

То, против чего возражает компилятор, является выражением cs.Head, поскольку из этого выражения он не может определить тип cs. Это может быть список Card s, но это также может быть любой другой класс с Head членом: в этот момент в коде , F # не может сказать, что такое cs. (Позже, когда вы делаете for i in cs do ... card_color i, этого будет достаточно для определения типа cs, но компилятор F # является однопроходным компилятором, поэтому, когда он встречает cs.Head, у него еще нет никаких других подсказок типа о тип cs.)

Определите тип cs в определении вашей функции следующим образом:

let all_same_color (cs : Card list) =
    // ...

и этого будет достаточно. Или вы также можете заменить cs.Head на List.head cs, и этого будет также , чтобы компилятор F # определил тип cs:

let col = card_color (List.head cs)

И вы заметите, что теперь нет необходимости указывать, что List.head cs является Card, или что col является Color, потому что сигнатура функции card_color позволяет F # вычислять все это из.

Кстати, есть еще более простой способ определить, все ли в вашем списке карт одного цвета, используя List.map и List.distinct:

let allSameColor cs =
    let distinctColors = cs |> List.map card_color |> List.distinct
    List.length distinctColors = 1

Две строки (которые могли бы даже быть одной строкой достаточно легко, но я подумал, что написать это в две строки сделает это проще), которые делают то же самое, что и ваша оригинальная функция all_same_color (и обратите внимание, что я использовал camelCase в моем имя функции, потому что camelCase является обычным соглашением для имен функций F #). Единственное отличие состоит в том, что у вашей функции есть побочные эффекты (печать «Black» или «Val: (что-то)»), в то время как я намеренно написал «чистую» функцию без побочных эффектов. Рекомендуется, чтобы каждая функция выполняла только одну вещь: либо возвращают значение или имеют побочный эффект, но не оба.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...