Tôi muốn có một chức năng như:Có cách nào hợp lý để giải nén đơn nguyên trạng thái không?
unzipState :: (MonadState s m) => m (a, b) -> (m a, m b)
trong đó sẽ có một (stateful) tính toán rằng trả về một tuple, và sẽ quay trở lại hai phép tính (phụ thuộc).
Khó khăn là tất nhiên trong đó trích xuất các giá trị từ một hoặc các tính toán khác nên cập nhật trạng thái trong khác.
Một hữu ích (và động cơ thúc đẩy) ứng dụng là đơn nguyên ngẫu nhiên, thể hiện dưới dạng
{-# LANGUAGE Rank2types #-}
import qualified System.Random as SR
import Control.Monad.State
type Random a = forall r. (State RandomGen r) => State r a
và giả sử bạn có:
normal :: Random Double
-- implementation skipped
correlateWith :: Double -> Random (Double, Double) -> Random (Double, Double)
correlateWith rho w = do
(u, v) <- w
return $ (u, p * u + (1 - p * p) * v)
nó sẽ là khá tự nhiên để có thể viết:
let x = normal
y = normal
(u, v) = unzipState $ correlateWith 0.5 $ liftM2 (,) x y
... now I am able to perform computation on u and v as correlated random variables
Có cách nào hợp lý để thực hiện việc này không? Tôi đã vật lộn một chút, nhưng không xoay sở được gì cả. Hoogle cũng chẳng giúp được gì.
chỉnh sửa
câu trả lời lớn đã cho tôi thấy vấn đề của tôi là mập mờ. Tuy nhiên, ai đó có thể giải thích cho tôi lý do tại sao thực hiện sau đây trong python (mà tôi tin là đúng, nhưng chưa được thử nghiệm nhiều) không thể dịch được trong Haskell (với sự kỳ diệu của STrefs, đóng cửa và những thứ khác tôi thừa nhận tôi không nắm ;-)):
def unzipState(p):
flist, glist = [], []
def f(state):
if not flist:
(fvalue, gvalue), newstate = p(state)
glist.insert(0, gvalue)
return (fvalue, newstate)
else:
fvalue = flist.pop()
return (fvalue, state)
def g(state):
if not glist:
(fvalue, gvalue), newstate = p(state)
flist.insert(0, fvalue)
return (fvalue, newstate)
else:
gvalue = glist.pop()
return (gvalue, state)
return (f, g)
không phải là tôi nói rằng mã stateful có thể được dịch trong Haskell, nhưng tôi cảm thấy như sự hiểu biết lý do tại sao và khi (ngay cả trên một ví dụ) nó không thể được thực hiện sẽ nâng cao hiểu biết của tôi rất nhiều.
edit2
Bây giờ nó là tinh thể rõ ràng. Các functons f và g rõ ràng là không thuần túy, vì đầu ra của chúng không chỉ phụ thuộc vào giá trị của trạng thái.
Cảm ơn bạn lần nữa!
Tôi không nghĩ rằng (Random a) thực sự có thể được hiểu là phân phối xác suất bởi vì trong trường hợp đó, bạn cần có khả năng xác định omega là một không gian được lập trình, điều này khá khó. Hơn nữa, không phải vì hai đối tượng của Random a có cùng phân phối giống nhau (lấy hai u = uniform; v = uniform, bạn don 'có u = v). Một cách giải thích khiêm tốn hơn là hiểu nó như là sự hiện thực hóa (cụ thể hơn, như các hàm hoạt động trên sự hiện thực hóa) của các biến ngẫu nhiên, cần phải đồng nhất với các luồng, vì vậy tôi tin rằng hoạt động giải nén được xác định rõ). – LeMiz
Không. Nếu 'u = uniform :: Random A' và' v = uniform :: Random A', thì đúng là trivially true 'u = v = uniform'. Hãy nhớ rằng có hai khái niệm khác nhau ở đây: các biến ngẫu nhiên bắt nguồn từ một không gian mẫu Ω, và các tập hợp các giá trị kiểu 'a' có trọng số xác suất (= phân bố xác suất). Chữ 'Random a' của bạn tương ứng với chữ cái thứ hai, không phải là cái cũ. Cũng có thể thực hiện nó như là 'Random a = [(a, Probability)]'. [Tôi sợ có một chút khó khăn khi thảo luận về điều này mà không cần chính thức hóa đơn nguyên mẫu ngẫu nhiên và hiệu ứng cụ thể mà bạn đang làm.] –
bạn hoàn toàn đúng về điểm bình đẳng, tôi đã nhầm lẫn. Cảm ơn ! – LeMiz