F # If оператор, ожидающий от float - PullRequest
2 голосов
/ 10 мая 2019

оператор в порядке, пока в конечном элифе, который затем содержит ошибку "Ожидалось, что он будет иметь тип единицы"

type BankAcc = {AccNum:int; mutable  Balance:float} with

    member this.Withdraw(amount,?withdrawal) =
     let withdrawAmount = this.Balance * float amount
     match withdrawal with
      | None -> withdrawAmount
      | Some deduct -> withdrawAmount - deduct
let Account ={AccNum=123;Balance = 15.00}

Account.Withdraw(25.00) // withdrawing 25 from an account with a balance of 15

let test Balance withdrawAmount =
  if Balance = withdrawAmount then "Equals"
  elif Balance < withdrawAmount then "Balance too low"
  else Balance - withdrawAmount 

  Account={AccNum =0001; Balance=0.00};   

let CheckAccount Balance = 
    if Balance < 10.00 then "Balance is low"
    elif Balance >= 10.00 && Balance <= 100.00 then "Balance is ok"
    elif Balance > 100.00 then "balance is high"

let sort = Seq.unfold(fun Balance -> if(snd Balance => 50)then List.map(fun accounts-> Balance <50) list1)

1 Ответ

8 голосов
/ 10 мая 2019

Итак, давайте немного абстрагируем ваш код:

if a then b
elif x then y
elif p then q

Исходя из этого, компилятор может сказать, что при a = true результат должен быть b.Когда a = false, он должен проверить x next, а если x = true, результат должен быть y.Теперь, если оба значения a и x окажутся false, компилятор знает, что нужно перейти к проверке p, а если p = true, то результат будет q.

Но вот вопрос: каким должен быть результат, когда все три, a, b и p окажутся ложными?

Вы не сказали компилятору, что делать в этомслучай, так что, конечно, он жалуется!


Но почему он так загадочно жалуется?При чем тут unit?

Это связано с небольшим синтаксическим ослаблением, которое существует в F # для облегчения жизни разработчиков.Видите ли, поскольку F # не является функциональным языком pure , что означает, что он может иметь произвольные побочные эффекты, очень часто эти побочные эффекты не возвращают никакого значимого значения, например printf, например:

> printf "foo"
it : unit = ()

Функция не имеет ничего хорошего для возврата, но должен быть какой-то тип возврата, и для этого есть специальный тип - unit.Это специальный тип, который имеет ровно одно значение, поэтому он ничего не значит.

Теперь давайте посмотрим, что произойдет, если мне нужно поместить мой вызов printf в if: в любой ifобе ветви then и else должны иметь один и тот же тип, иначе неясно, каким должен быть тип всего выражения if.Поэтому, если моя ветка then содержит printf, моя ветвь else также должна иметь тип unit.Поэтому я вынужден всегда помещать туда это бессмысленное приложение:

> if foo then printf "bar" else ()
it : unit = ()

Это раздражает.На самом деле, так досадно, что у языка F # есть особый случай: когда моя ветка then имеет тип unit, я могу вообще пропустить ветку else, и компилятор просто предположит, что я имел в видусказать else ():

> if foo then printf "bar"
it : unit = ()

Так вот, что происходит в вашем случае: так как вы пропустили ветку else, компилятор предполагает, что все ветви then должны быть типа unit, но они явно относятся к типу float, поэтому компилятор жалуется.


Чтобы это исправить, вам нужно предоставить ветку else.Судя по вашему коду, мне кажется, что вы действительно имели в виду возможные случаи: (1) менее 10, (2) от 10 до 100 и (3) все остальное.Если так, то ветвь «все остальное» должно быть else:

if Balance < 10.00 then "Balance is low" 
elif Balance >= 10.00 && Balance <= 100.00 then "Balance is ok" 
else "balance is high"

PS. После того, как вы исправите это, у вас будет похожая проблема в функции test: дваthen ветви string, но else ветви float

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