user5363938
user5363938

Reputation: 841

This expression was expected to have type unit

I have the following code. in this line

 if min<=0  then     min <- List.nth list i |>ignore

i have 2 errors. first in 0 it is

 This expression was expected to have type
    unit    
but here has type
    int

and then in i it is

This expression was expected to have type
    unit    
but here has type
    int

* I have also seen this and tried ignore, but it doesn't work

let replace touple2=
   let first  (a,_,_,_,_)=a
   let second (_,b,_,_,_)=b
   let third  (_,_,c,_,_)=c
   let forth  (_,_,_,d,_)=d
   let fifth  (_,_,_,_,e)=e
   let sortedlist list= List.sort(list)

   let GetMin list=
        list |> List.rev |> List.head
        let mutable min=list.Head
        let mutable i=1
        for i in list do     
            if min<=0  then     min <- List.nth list i |>ignore

        min 

   let GetMax list=list |> List.rev |> List.head

   let A=first  touple2
   let B=second touple2
   let C=third  touple2
   let D=forth  touple2
   let E=fifth  touple2
   let mylist=[A;B;C;D;E]
   let L=sortedlist mylist

   let m1=GetMax L
   printfn "%d"  m1

let touple3= 14,6,18,76,76
replace touple3

Upvotes: 1

Views: 2744

Answers (3)

CaringDev
CaringDev

Reputation: 8551

The first problem is list |> List.rev |> List.head causing the compiler to infer listto be of type unit. If you delete that line (as it's meaningless anyways, F# lists are immutable, so you are computing an unused value), list is correctly inferred to have type int list which makes the first error go away (if we also use List.head list instead of list.Head to make type inference happy).

Then, a second error appears on this line if min<=0 then min <- List.nth list i |>ignore which makes sense, as an assignment to a mutable variable should leave nothing to |> ignore. So lets get rid of that, fix the deprecation warning and add a bit of formatting... this compiles:

let replace touple2 =
   let first  (a,_,_,_,_) = a
   let second (_,b,_,_,_) = b
   let third  (_,_,c,_,_) = c
   let forth  (_,_,_,d,_) = d
   let fifth  (_,_,_,_,e) = e
   let sortedlist list= List.sort(list)

   let GetMin list=
        let mutable min = List.head list
        let mutable i = 1
        for i in list do     
            if min <= 0 then min <- List.item i list

        min 

   let GetMax list = list |> List.rev |> List.head

   let A = first  touple2
   let B = second touple2
   let C = third  touple2
   let D = forth  touple2
   let E = fifth  touple2
   let mylist = [A;B;C;D;E]
   let L = sortedlist mylist

   let m1 = GetMax L
   printfn "%d" m1

let touple3 = 14,6,18,76,76
replace touple3

Still, it doesn't really look F#-ish. How about this (including wild guesses what you want to achieve):

let printMinMax (a, b, c, d, e) =

    let minPositive sortedList = 
        sortedList |> List.fold (fun m e -> if m <= 0 then e else m) sortedList.Head

    let max sortedList = sortedList |> List.last

    let sortedList = [ a; b; c; d; e ] |> List.sort

    printfn "min %d, max %d" (minPositive sortedList) (max sortedList)

let t1 = 14, 6, 18, 76, 76
printMinMax t1

let t2 = -1, -5, 5, 16, 12
printMinMax t2

This could be improved further, but I fear the connection to the original becomes even less obvious (and it expects at least one positive value to be present):

let minMax (a, b, c, d, e) =
    let l = [ a; b; c; d; e ] |> List.sortDescending
    let positiveMin = l |> List.findBack ((<) 0)
    let max = l.Head
    positiveMin, max

let t1 = 14, 6, 18, 76, 76
let t2 = -1, -5, 5, 16, 12

let test t =
    let min, max = minMax t
    printfn "min (positive) %d, max %d" min max

test t1
test t2

Upvotes: 0

Tomas Petricek
Tomas Petricek

Reputation: 243096

You do not need the ignore - if you are using assignment, it returns unit and so you do not have any return value that would have to be ignored:

if min <= 0 then min <- List.nth list I

That said, this is not very functional approach. So looking into some basic F# book or watching a few talks might help you get started with the langauge in a more F# style.

Upvotes: 5

William Barbosa
William Barbosa

Reputation: 5005

You just need parentheses to make your intentions clear to the compiler:

if min <= 0 then (min <- List.nth list i) |> ignore

An if without an else in F# is a shorthand for:

if condition then doSomething else ()

It means the result of whatever is inside the doSomething block must be of type unit. Since an assignment in F# is an expression, your code was returning min, an int value. This explains your first error.

The above happened because, without the parenthesis, the pipe operator was using last parameter os List.nth, the i as the parameter to ignore

Upvotes: 3

Related Questions