使用Data.Machine,您将如何描述分支非确定性函数结果的计划?

时间:2013-07-10 17:47:21

标签: haskell transducer-machines

我认为这个问题最好用一个例子说明。

包含非确定性函数的类型:

data ND a b = N { runN :: a -> [(b, ND a b)] }

instance Show (ND a b) where
    show n = show "<ND>"

ND的一个例子:

nd :: ND String Int
nd = N $ \a -> case a of 
    "hello" -> [(length a, nd), (length a + 100, nd)]
    "world" -> [(length a + 10, nd)]
    _       -> []

备注:请注意nd如何输出元组列表,每个元组包含计算结果,以及新的ND(实际上与原始元组相同,但现在让我们忽略它。)

现在构建一个从源接收输入并为所有输入运行nd的进程。

错误的Process

-- | Please note this is wrong, since only the first result of computation is used
toProcess :: ND a b -> Process a b
toProcess = construct . plan where
    plan n = do 
        a <- await
        case runN n a of 
            []          -> stop
            ((b,n'):xs) -> yield b >> plan n' 

备注:上面的这个过程是错误的,因为只采取了第一个计算结果。理想情况下,该进程应分支到多个并行进程,每个进程产生一个输出b,并使用自己的n'版本进行递归。最终结果应该是可能结果列表

用例:

 ret :: [Int]
 ret = run $ source ["hello", "world", "again"] ~> toProcess nd

 -- Run with toProcess above:
 [5,15]

 -- But ideally, should yield a list of possible results:
 [[5,15],[105,15]]

1 个答案:

答案 0 :(得分:2)

我相信你需要将你的计算嵌入到[] monad中,这是一种如何对非确定性计算进行建模的自然方法。然后,您将拥有ProcessT []PlanT []等等:

toProcess :: ND a b -> ProcessT [] a b
toProcess = construct . plan where
    plan n = do 
        a <- await
        case runN n a of
            []  -> stop
            xs  -> do
                (b, n') <- lift xs
                yield b
                plan n'

ret :: [[Int]]
ret = runT $ source ["hello", "world", "again"] ~> toProcess nd
-- produces: [[5,15],[105,15]]