động lực. Tôi đang cố gắng để tạo ra một biến áp đơn lẻ, với một hướng dẫn đặc biệt f <||> g
có nghĩa là "lặp lại toàn bộ khối này có chứa f <||> g
, một lần với f
, lần sau với g
". Điều này được dự định là để chuyển đổi DSL, mặc dù bạn có thể tưởng tượng các ứng dụng khác.làm thế nào tôi có thể thực hiện biến áp đơn nguyên này với sự tiếp tục?
ví dụ về cách sử dụng. Các đơn vị computation
thể hiện các lựa chọn khác nhau có thể (trong trường hợp này, những thứ cần in). Hàm printme
cho biết phải làm gì với mỗi kết quả khác nhau. Trong trường hợp này, chúng tôi in "bắt đầu tính toán" trước khi nó chạy, và "---" sau.
computation = do
lift (print "start -- always")
(lift (print "first choice") <||> lift (print "second choice"))
lift (print "intermediate -- always")
(lift (print "third choice") <||> lift (print "fourth choice"))
lift (print "end -- always")
printme x = do
putStrLn "=== start computation"
xv <- x
putStrLn "---\n"
return xv
test = runIndep printme computation
đầu ra là như sau,
=== start computation
"start -- always"
"first choice"
"intermediate -- always"
"third choice"
"end -- always"
---
=== start computation
"start -- always"
"first choice"
"intermediate -- always"
"fourth choice"
"end -- always"
---
=== start computation
"start -- always"
"second choice"
"intermediate -- always"
"third choice"
"end -- always"
---
=== start computation
"start -- always"
"second choice"
"intermediate -- always"
"fourth choice"
"end -- always"
---
câu hỏi. Có cách nào sạch sẽ để đạt được các hành vi trên bằng cách sử dụng một số loại tiếp tục đi qua biến áp kiểu đơn? Tôi đã xem xét bài báo "Backtracking, Interleaving, and Terminating Unad Transformers" của Oleg và cộng sự, nhưng dường như không thể nắm bắt đầy đủ việc thực hiện của họ (một khi họ có thể thực hiện msplit
với sự tiếp tục).
triển khai hiện tại. Triển khai hiện tại của tôi là chuyển một danh sách các quyết định phân nhánh được thực hiện. Đơn nguyên sẽ trả về danh sách các nhánh mà nó thực sự chọn, và lần sau chúng ta sẽ chuyển nhánh cuối cùng có thể. Mã này là như sau (nên chạy ở 7.0.3),
import Control.Monad.Trans.Class
data IndepModelT α = IndepModelT {
unIndepModelT :: [Bool] -> (α, [Bool]) }
instance Monad => Monad (IndepModelT) where
return x = IndepModelT $ \choices -> return (x, [])
(IndepModelT x) >>= f = IndepModelT $ \choices -> do
(xv, branches) <- x choices
let choices' = drop (length branches) choices
(fxv, branches') <- unIndepModelT (f xv) choices'
return (fxv, branches ++ branches')
instance MonadTrans IndepModelT where
lift x = IndepModelT $ \c -> liftWithChoice [] x
liftWithChoice cs mx = mx >>= \xv -> return (xv, cs)
(<||>)
:: Monad => IndepModelT α -> IndepModelT α -> IndepModelT α
(IndepModelT f) <||> (IndepModelT g) = IndepModelT go where
go (False:cs) = do
(fv, branches) <- f cs
return (fv, False : branches)
go (True:cs) = do
(fv, branches) <- g cs
return (fv, True : branches)
run_inner next_choices k [email protected](IndepModelT comp_inner) = do
(xv, branches) <- k $ comp_inner next_choices
case (get_next_choices branches) of
Nothing -> return()
Just choices -> run_inner (choices ++ repeat False) k comp
where
get_next_choices [] = Nothing
get_next_choices [True] = Nothing
get_next_choices [False] = Just [True]
get_next_choices (c:cs)
| Just cs' <- get_next_choices cs = Just $ c:cs'
| c Prelude.== False = Just [True]
| otherwise = Nothing
runIndep :: Monad =>
((α, [Bool]) -> (β, [Bool]))
-> IndepModelT α
-> ()
runIndep = run_inner (repeat False)
runIndepFirst (IndepModelT comp) = comp (repeat False)
Bạn đã xem http://www.haskell.org/haskellwiki/ListT_done_right và đặc biệt là triển khai thay thế http: // www. haskell.org/haskellwiki/ListT_done_right_alternative? –
Tôi không nghĩ bạn cần tiếp tục. Những gì bạn dường như có là một loại cây, trong đó mỗi hoạt động <||> đại diện cho một chi nhánh. Nhưng tôi không thể tìm ra loại dữ liệu phù hợp. –