【问题标题】:Recursive call in if expression - ocamlif 表达式中的递归调用 - ocaml
【发布时间】:2017-08-14 15:59:46
【问题描述】:
    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 -> string 但是需要一个类型为 'a -> unit 的表达式 类型字符串与类型单位不兼容 在 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

【问题讨论】:

    标签: function loops recursion ocaml


    【解决方案1】:

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

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

    作为旁注,您几乎可以肯定这段代码存在优先级问题:

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

    dfslsts的函数调用的优先级高于列表cons运算符::,因此解析为:

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

    你可能需要像这样加括号:

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

    【讨论】:

    • (这是一个旁注。请告诉我们您的图表类型的定义。)
    • 我已经更新了包含图形结构的问题。
    • 这里 (List.flatten l) 是一个列表,final 是列表的列表。使用 :: 这个符号是否有问题
    猜你喜欢
    • 1970-01-01
    • 2013-01-23
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    相关资源
    最近更新 更多