0
votes

So this is the context. Assuming that I have a function that takes a tuple of 2 experiments and test it against a list of rules. The function should stop whenever the tuple of experiments are correctly verified by a certain rule.

type exp = A | B | Mix of exp * exp | Var of string

type sufficency = exp * exp  

type rule = Rule of sufficency * (sufficency list) 


let rec findout rules (exp1, exp2) = // return a boolean value
            match rules with
            | [] -> true
            | thisRule::remaining ->
                match thisRule with
                | (suff, condition) ->
                    match suff with
                    | (fstExp, sndExp) ->
                        let map1 = unify Map.empty exp1 fstExp // I don't mention this function in here, but it is defined in my code
                        let map2 = unify Map.empty exp2 sndExp
                        true
                findout remaining (exp1, exp2)

The problem is, I have no idea how this could be done with functional programming like this. With imperative programming, it would be easier to loop through the list of rules, rather using recursion to go over the list.

So what should the function return at each stage of the recursion?

I got the warning with that code above

warning FS0020: This expression should have type 'unit', but has type 'bool'. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name.

1
Your code for unify is missing. Also, functional <> recursive. Feel free to use List.tryFind and friends. - John Palmer
Hi John, I didn't mention the unify function in my post, but it's defined in my code. - user2431438
Instead of multiple single-case match statements, you can deconstruct the entire head of the list at once: | ((fstExp, sndExp), condition) :: remaining ->. Also it looks like your case for the empty list should return false, otherwise findout will always return true. - Lee

1 Answers

2
votes

So the problem is in this part of the code

            match thisRule with
            | (suff, condition) ->
                match suff with
                | (fstExp, sndExp) ->
                    let map1 = unify Map.empty exp1 fstExp // I don't mention this function in here, but it is defined in my code
                    let map2 = unify Map.empty exp2 sndExp
                    true
            findout remaining (exp1, exp2)

The first match returns true so you get a warning. You probably wanted

            match thisRule with
            | (suff, condition) ->
                match suff with
                | (fstExp, sndExp) ->
                    let map1 = unify Map.empty exp1 fstExp // I don't mention this function in here, but it is defined in my code
                    let map2 = unify Map.empty exp2 sndExp
                    true && findout remaining (exp1, exp2)

Where you carry the true through the calculation. However, this would probably all be simpler if you used the various List.* functions.