Tying the Knot with a State monad

后端 未结 5 1932
隐瞒了意图╮
隐瞒了意图╮ 2021-01-30 16:42

I\'m working on a Haskell project that involves tying a big knot: I\'m parsing a serialized representation of a graph, where each node is at some offset into the file, and may r

5条回答
  •  青春惊慌失措
    2021-01-30 17:16

    I'm kind of overwhelmed by the amount of Monad usage. I might not understand the past/future things, but I guess you are just trying to express the lazy+fixpoint binding. (Correct me if I'm wrong.) The RWS Monad usage with R=W is kind of funny, but you do not need the State and the loop, when you can do the same with fmap. There is no point in using Monads if they do not make things easier. (Only very few Monads represent chronological order, anyway.)

    My general solution to tying the knot:

    1. I parse everything to a List of nodes,
    2. convert that list to a Data.Vector for O(1) access to boxed (=lazy) values,
    3. bind that result to a name using let or the fix or mfix function,
    4. and access that named Vector inside the parser. (see 1.)

    That example solution in your blog, where you write sth. like this:

    data Node = Node {
      value :: Int,
      next  :: Node
    } deriving Show
    …
    tie = …
    parse = …
    data ParserState = …
    …
    example :: Node
    example =
      let (_, _, m) = tie parse $ ParserState 0 [(0, 1), (1, 2), (2, 0)]
      in (m Map.! 0)
    

    I would have written this way:

    {-# LANGUAGE ViewPatterns, NamedFieldPuns #-}
    import Data.Vector as Vector
    
    example :: Node
    example =
       let node :: Int -> Node
           node = (Vector.!) $ Vector.fromList $
                       [ Node{value,next}
                       | (value,node->next) <- [(0, 1), (1, 2), (2, 0)]
                       ]
       in (node 0)
    

    or shorter:

    {-# LANGUAGE ViewPatterns, NamedFieldPuns #-}
    import Data.Vector as Vector
    
    example :: Node
    example = (\node->(Vector.fromList[ Node{value,next}
                                      | (value,node->next) <- [(0, 1), (1, 2), (2, 0)]
                                      ] Vector.!)) `fix` 0
    

提交回复
热议问题