How to enumerate a recursive datatype in Haskell?

后端 未结 4 1408
北荒
北荒 2020-12-01 12:57

This blog post has an interesting explanation of how to use the Omega monad to enumerate an arbitrary grammar diagonally. He offers an example of how to do so, resulting in

4条回答
  •  伪装坚强ぢ
    2020-12-01 13:41

    You really should show us what you have tried so far. But granted, this is not an easy problem for a bgeinner.

    Let's try to write a naive version down:

    enum = A : (map B enum ++ [ C x y | x <- enum, y <- enum ])
    

    Ok, this actually gives us:

    [A, B A, B (B A), B (B (B A)), .... ]
    

    and never reaches the C values.

    We obviously need to construct the list in steps. Say we already have a complete list of items up to a certain nesting level, we can compute the items with one nesting level more in one step:

    step xs = map B xs ++ [ C x y | x <- xs, y <- xs ]
    

    For example, we get:

    > step [A]
    [B A,C A A]
    > step (step [A])
    [B (B A),B (C A A),C (B A) (B A),C (B A) (C A A),C (C A A) (B A),C (C A A) (C A ...
    

    What we want is thus:

    [A] ++ step [A] ++ step (step [A]) ++ .....
    

    which is the concatenation of the result of

    iterate step [A]
    

    which is, of course

    someT = concat (iterate step [A])
    

    Warning: You will notice that this still does not give all values. For example:

    C A (B (B A))
    

    will be missing.

    Can you find out why? Can you improve it?

提交回复
热议问题