Haskell Reference List Completion

EDIT: see this next question , which simplifies the problem I'm trying to identify here, and asks for input in a suggestion for modifying the GHC.

So, I tried to write a universal width search function and came up with the following:

bfs :: (a -> Bool) -> (a -> [a]) -> [a] -> Maybe a
bfs predf expandf xs = find predf bfsList
    where bfsList = xs ++ concatMap expandf bfsList

which, as I thought, was rather elegant, but in the case does not exist, it is blocked forever.

After all the terms have been expanded to [], concatMapwill it never return another element, why does it concatMapblock the expectation of another element from itself? Can Haskell be smart enough to realize that list generation is blocked by reading self-regulation and completing the list?

The best replacement I could come up with is not so elegant, as I myself have to handle the completion case myself:

    where bfsList = concat.takeWhile (not.null) $ iterate (concatMap expandf) xs

For specific examples, the first search succeeds, and the second blocks:

bfs (==3) (\x -> if x<1 then [] else [x/2, x/5]) [5, 3*2**8]
bfs (==3) (\x -> if x<1 then [] else [x/2, x/5]) [5, 2**8]
+4
source share
3 answers

We create a list of results (queue) in steps. At each step, we use what we did in the previous step. When the last expansion step has added nothing, we stop:

bfs :: (a -> Bool) -> (a -> [a]) -> [a] -> Maybe a
bfs predf expandf xs = find predf queue
    where 
    queue = xs ++ gen (length xs) queue                 -- start the queue with `xs`, and
    gen 0 _ = []                                        -- when nothing in queue, stop;
    gen n q = let next = concatMap expandf (take n q)   -- take n elemts from queue,
              in  next ++                               -- process, enqueue the results,
                         gen (length next) (drop n q)   -- advance by `n` and continue

So we get

~> bfs (==3) (\x -> if x<1 then [] else [x/2, x/5]) [5, 3*2**8]
Just 3.0

~> bfs (==3) (\x -> if x<1 then [] else [x/2, x/5]) [5, 2**8]
Nothing

One potentially serious flow in this solution is that if any step expandfcreates an endless list of results, it will get stuck calculating it lengthis completely useless.


, , (length . concatMap expandf - ), , . 0, , , .

. n , , , n , . 1 , .

corecursion ( " " ):

data Tree a b = Leaf a  |  Branch b (Tree a b) (Tree a b)

bftrav :: Tree a b -> [Tree a b]
bftrav tree = queue
  where
    queue = tree : gen 1 queue                -- have one value in queue from the start

    gen  0   _                 =         []           
    gen len (Leaf   _     : s) =         gen (len-1) s   -- consumed one, produced none
    gen len (Branch _ l r : s) = l : r : gen (len+1) s   -- consumed one, produced two

Prolog , , . . .


gen bfs , :

    gen 0  _     = []
    gen n (y:ys) = let next = expandf y
                   in  next ++ gen (n - 1 + length next) ys
+4

, , bfs' .

( " " ), , , :

bfs (\x -> False) (\x -> []) []

bfs Nothing, Haskell .

- . bfs ( [] ++), :

find (\x -> False) bfsList
   where bfsList = concatMap (\x -> []) bfsList

find , bfsList , . concatMap, , bfsList , WHNF. , bfsList , find.

Haskell , [].

, , :

foo = case foo of [] -> []

. Haskell , case foo, foo foo, . , , foo = [] " " , , Haskell , :

bar = bar

1 "awesome", "".

, : , , Haskell.

, , - - , :

bfs' :: (a -> Bool) -> (a -> [a]) -> [a] -> Maybe a
bfs' predf expandf = look
  where look [] = Nothing
        look xs = find predf xs <|> look (concatMap expandf xs)

Alternative Maybe, :

Just x  <|> ...     -- yields `Just x`
Nothing <|> Just y  -- yields `Just y`
Nothing <|> Nothing -- yields `Nothing` (doesn't happen above)

look xs find, Nothing, .

, , (, Reader) listToMaybe ! ( .)

bfs'' :: (a -> Bool) -> (a -> [a]) -> [a] -> Maybe a
bfs'' predf expandf = look
  where look = listToMaybe *>* find predf *|* (look . concatMap expandf)

        (*>*) = liftM2 (>>)
        (*|*) = liftM2 (<|>)
        infixl 1 *>*
        infixl 3 *|*

? , . look :

  where look xs = listToMaybe xs >> 
                  (find predf xs <|> look (concatMap expandf xs))
+4

bfsList , Haskell. , , , , Haskell .

find , , , , (, , ).

AFAICT, , , bfsList , find .

, [], concatMap

, ? , - - []. , , , , , .

Haskell , , , ?

, , , . , ( ), 1936 , . . , , , , , ...

, ,

... bfsList, ... , , .a >

+1

Source: https://habr.com/ru/post/1686471/


All Articles