문제

Let's say there is a graph and some set of functions like:

create-node :: Graph -> (Graph, Node)
split-node :: Graph -> Node -> (Graph, Node, Node)

I would like to create versions of those functions that don't expect Graph as an argument, mainly for convenience (preferably without monads so I wouldn't need to wrap every graph manipulating piece of code in a monad block). So what about this:

create-node :: (Graph -> (Graph, Node))
split-node :: (Graph -> Node) -> ((Graph -> Node), (Graph -> Node))

Or more generally:

fun :: (Graph -> Argument) -> ... -> (Graph -> Result)

I would then be able to use the (Graph -> ...) values as if they were normal nodes. In the end, to get a real graph out of a (Graph -> ...) value, just apply it to an empty graph. Is this a reasonable approach?

도움이 되었습니까?

해결책

Ok, so

create-node :: (Graph -> (Graph, Node))

is the state monad, just without the fancy newtype (and a flipped return value). So I don't see the advantage of not using State here. After all that lets me write fairly clean code using the state Monad:

 reverseEdgesM :: State Graph ()
 reverseEdgesM = do --...

Then pop out of it whenever I've got some pure code to run using runState and friends:

 reverseEdges :: Graph -> Graph
 reverseEdges = execState reverseEdgesM

If you do want to push forward with your functions idea, you may want to look into difference lists to see how its done with simple lists.

Also, if you've just got some algorithms to implement, you may want to look into existing functional graph data structure libraries (like fgl), rather than rolling your own. If you want to understand the theory, check out Erwig's paper on inductive graphs.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top