0
votes
    module Dfs = struct 
    let rec dfslsts g paths final =
        let l = PrimePath.removeDuplicates (PrimePath.extendPaths g paths)
        in
        let f elem =
            if  (List.mem "%d" (List.flatten final) = false) then (dfslsts g ["%d"] (List.flatten l)::final) 
            else final 
        in
        List.iter f (Graph.nodes g)

    end

Error: This expression has type string but an expression was expected of type int list

This error occurred when I called dfslsts function, which is recursive, inside the if condition. The function dfslsts returns a list of lists. If I try to replace the complex expression in if statement to

if  (List.mem "%d" (List.flatten final) = false) then "%d"
else "%d"

then I get Error: This expression has type 'a -> string but an expression was expected of type 'a -> unit Type string is not compatible with type unit at List.iter line.

How do I solve this problem and are we allowed to call a recursive function inside the if expression.

This is the definition of my graph type:

    module Graph = struct

    exception NodeNotFound of int

    type graph = {
        nodes : int list;
        edges : (int * int) list;
    }

    let makeGraph () =
        {
            nodes = [];
            edges = [];
        }

    let rec isNodeOf g n = List.mem n g.nodes

    let nodes g = g.nodes

    let edges g = g.edges

    let addNode g n =
        let nodes = n::g.nodes and edges = g.edges in
        {
            nodes;
            edges;
        }

    let addEdge g (n1, n2) =
        if ((isNodeOf g n1) = false) then
            raise (NodeNotFound n1)
        else if ((isNodeOf g n2) = false) then
            raise (NodeNotFound n2)
        else
            let nodes = g.nodes
            and edges = (n1, n2) :: g.edges in
            {
                nodes;
                edges;
            }

    let nextNodes g n =
        let rec findSuccessors edges n =
            match edges with
              [] -> []
            | (n1, n2) :: t ->
                if n1 = n then n2::findSuccessors t n
                else findSuccessors t n
        in
        findSuccessors g.edges n

    let rec lastNode path =
        match path with
          [] -> raise (NodeNotFound 0)
        | n :: [] -> n
        | _ :: t -> lastNode t

end

module Paths = struct
    let extendPath g path =
        let n         = (Graph.lastNode path) in
        let nextNodes = Graph.nextNodes g n   in
        let rec loop path nodes =
            match nodes with
              []     -> []
            | h :: t -> (List.append path [h]) :: (loop path t)
        in
        loop path nextNodes

    let rec extendPaths g paths =
        match paths with
          []     -> []
        | h :: t -> List.append (extendPath g h) (extendPaths g t) 

    (* Given a list lst, return a new list with all duplicate entries removed *)
    let rec removeDuplicates lst =
        match lst with
          []
        | _ :: [] -> lst
        | h :: t  ->
            let trimmed = removeDuplicates t in
            if List.mem h trimmed then trimmed
            else h :: trimmed

end
1

1 Answers

1
votes

Any expression can be a recursive function call. There are no limitations like that. Your problem is that some types don't match.

I don't see any ints in this code, so I'm wondering where the compiler sees the requirement for an int list. It would help to see the type definition for your graphs.

As a side comment, you almost certainly have a precedence problem with this code:

dfslsts g ["%d"] (List.flatten l)::final

The function call to dfslsts has higher precedence that the list cons operator ::, so this is parsed as:

(dfslsts g ["%d"] (List.flatten l)) :: final

You probably need to parenthesize like this:

dfslsts g ["%d"] ((List.flatten l) :: final)