if表达式中的递归调用 - ocaml

时间:2017-03-22 13:39:12

标签: function loops recursion ocaml

    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

错误:此表达式具有类型字符串,但表达式需要类型为int list

当我在if条件中调用dfslsts函数(递归)时发生此错误。 函数dfslsts返回列表列表。 如果我尝试将if语句中的复杂表达式替换为

if  (List.mem "%d" (List.flatten final) = false) then "%d"
else "%d"
然后我明白了 错误:此表达式的类型为'a - >串        但是预期表达式为'a - >单元        类型字符串与类型单位不兼容 在List.iter行。

如何解决这个问题,我们允许在if表达式中调用递归函数。

这是我的图表类型的定义:

    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 个答案:

答案 0 :(得分:1)

任何表达式都可以是递归函数调用。没有这样的限制。你的问题是某些类型不匹配。

我在这段代码中没有看到任何内容,所以我想知道编译器在哪里看到int列表的要求。查看图表的类型定义会有所帮助。

作为旁注,您几乎肯定会对此代码存在优先级问题:

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

dfslsts的函数调用优先于list cons运算符::,因此将其解析为:

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

您可能需要像这样括号:

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