'Dfs to find visited nodes in sml
What is wrong with this part of code ? I'm trying to make a function which (given a graph) returns a list with all visited nodes, but the compiler keeps saying that there are some erros. Can the code be fixed ?The succesors function is used to find all nodes that are connected to the node which is takes as a parameter. I need dfs function in order to check if the returned "visited" list has all nodes, or in other words if the graph has all nodes connected to each other with a path. -The parameter tuple is a list with tuples of form (weight,node1,node1).
fun succesors n e =
List.map (fn (_,v ,_) => v) (List.filter (fn (u,_,_) => n = u) e)
fun dfs tuples node start =
let
fun find_visited visited node =
if not (List.exists node visited) then
let
val s = (succesors node tuples)
in
List.foldl find_visited (node::visited) s
end
else visited
in
find_visited [] start
end
Those were the errors that were printed :
ask2_ml.sml:75.18-75.39 Error: operator and operand don't agree
[equality type required]
operator domain: ''Z
operand: 'Y -> bool
in expression:
succesors node
ask2_ml.sml:77.35-77.48 Error: operator and operand don't agree
[circularity]
operator domain: ('Z -> bool) * ('Z -> bool) list
operand: ('Z -> bool) * 'Z list
in expression:
node :: visited
ask2_ml.sml:72.7-79.16 Error: case object and rules don't agree [tycon
mismatch]
rule domain: _ list * (_ -> bool)
object: (_ * _) * 'Z
in expression:
(case (arg,arg)
of (visited,node) =>
if not (<exp> <exp>)
then let val <binding> in <exp> <exp> end
else visited)
ask2_ml.sml:81.3-81.24 Error: operator and operand don't agree [tycon
mismatch]
operator domain: _ * _
operand: 'Z list
in expression:
find_visited nil
uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:292.17-292.20
Solution 1:[1]
There were two problems in your code.
First, List.exists
is defined as:
val exists : ('a -> bool) -> 'a list -> bool
So List.exists node visited
is incorrect as node
is not a
function. You should instead do something like List.exists (fn n => n = node) visited
.
Second, List.foldl
is defined as:
val foldl : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
Here again List.foldl find_visited (node::visited) s
is incorrect since
find_visited
is of type 'a -> 'b -> 'a
.
By fixing these two issues I get the following:
fun successors n e =
List.map (fn (_,v ,_) => v) (List.filter (fn (u,_,_) => n = u) e);
fun dfs tuples node start = let
fun find_visited (node, visited) =
if List.exists (fn n => n = node) visited
then visited
else let
val s = successors node tuples
in
List.foldl find_visited (node::visited) s
end
in
find_visited (start, [])
end;
On a side note, it's extremely inefficient to implement visited
as a
list: each time you meet a node you will look at all previously
visited nodes to check if it's new (List.exists
). Same for your
implementation of your successor relation: traversing all edges of
your graph to find the successors of n
will be too slow.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | qouify |