15

Chương trình sau sử dụng trạng thái di chuyển ngược được cung cấp bởi đơn vị Tardis.Retrocausality trong Haskell: Từ Tardis đến RevState

{-# LANGUAGE RecursiveDo #-} 

import Control.Monad.Tardis 

lastOccurrence :: Int -> Tardis [Int]() Bool 
lastOccurrence x = mdo 
    sendPast (x : xs) 
    xs <- getFuture 
    return (not (elem x xs)) 

lastOccurrences :: [Int] -> Tardis [Int]() [Bool] 
lastOccurrences xs = mapM lastOccurrence xs 

main :: IO() 
main = 
    print $ flip evalTardis ([],()) $ lastOccurrences [3,4,6,7,4,3,5,7] 

Làm cách nào để thay thế đơn nguyên mẫu Tardis bằng đơn reverse State? Với đề nghị sau đây của tôi, main vòng lặp mãi mãi thay vì in [False,False,True,False,True,True,True,True] như với chương trình trên.

{-# LANGUAGE RecursiveDo #-} 

import Control.Monad.RevState 

lastOccurrence :: Int -> State [Int] Bool 
lastOccurrence x = mdo 
    put (x : xs) 
    xs <- get 
    return (not (elem x xs)) 

lastOccurrences :: [Int] -> State [Int] [Bool] 
lastOccurrences xs = mapM lastOccurrence xs 

main :: IO() 
main = 
    print $ flip evalState [] $ lastOccurrences [3,4,6,7,4,3,5,7] 
+1

Nếu câu hỏi của bạn không nhận được sự chú ý đầy đủ trên SO, vui lòng ping các tác giả gói như bản thân mình! Trình theo dõi sự cố và thông tin liên hệ của người duy trì thường có thể được tìm thấy trên hackage, ví dụ: http://hackage.haskell.org/package/rev-state –

Trả lời

14

bây giờ tôi đã tải về nguồn gốc của cả hai TardisRevState, và tôi bắt đầu hack vào chúng cho đến khi chúng gần như giống nhau:

  • tôi bỏ qua tất cả mọi thứ bên ngoài Trans.{Tarids,RevState} mô-đun, vì vậy mà tôi don 't phải bận tâm với những typeclasses
  • tôi loại bỏ các trạng thái chuyển tiếp-tuyên truyền của Tardis
  • tôi đổi tên Tardis-State

Sau một chút sắp xếp lại mã, tôi đã kết thúc trong một tình huống mà ví dụ sử dụng Tardis vẫn còn hoạt động và ví dụ RevState của bạn vẫn không hoạt động.

Sự khác biệt tối thiểu đó là gì, bạn hỏi? Không ngạc nhiên, ví dụ MonadFix. Tardis has this:

instance MonadFix m => MonadFix (TardisT bw fw m) where 
    mfix f = TardisT $ \s -> do 
    rec (x, s') <- runTardisT (f x) s 
    return (x, s') 

trong khi RevState has this:

instance MonadFix m => MonadFix (StateT s m) where 
    mfix f = StateT $ \s -> 
    mfix (\(x, _) -> runStateT (f x) s) 

Trong khi họ có vẻ giống nhau, sự khác biệt lớn là các RevState một là nghiêm ngặt trong constructor tuple, trong khi Tardis một là lười biếng. (xem ví dụ: GHC documentation on RecursiveDo để xem rằng Tardis một desugars thành một kết hợp mẫu không thể chối cãi trong lambda được chuyển đến mfix).

Trên thực tế, thay đổi việc thực hiện RevState để

instance MonadFix m => MonadFix (StateT s m) where 
    mfix f = StateT $ \s -> do 
    mfix (\ ~(x, _) -> runStateT (f x) s) 

sửa của bạn chương trình • nhập gốc RevState.

+2

Tôi đã báo cáo vấn đề này là lỗi ở thượng nguồn: https://github.com/DanBurton/rev-state/issues/2 – Cactus

+7

Tác giả của Tardis và rev - ở đây. Có thể xác nhận, đây là một lỗi. Tôi vừa tải lên rev-state-0.1.1 với bản sửa lỗi được đề xuất của Cactus, và biến ví dụ này thành một trường hợp thử nghiệm. Cảm ơn vì đã xem xét điều đó! –

Các vấn đề liên quan