2014-09-05 22 views
6

Haskell có thể lấy được cá thể cho MonadState s trong T1 dưới đây nhưng không phải trong T2 mà là một loại rất giống nhau. Tôi nên sửa đổi mã nào cho T2 để phiên bản cho MonadState s có thể được tự động bắt nguồn?Generalized Newtype Deriving

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

import Control.Monad.Reader 
import Control.Monad.State 

newtype T1 r s a = 
    T1 { runT1 :: ReaderT r (State s) a } 
    deriving (Monad, MonadReader r, MonadState s) 

newtype T2 r s a = 
    T2 { runT2 :: StateT r (State s) a } 
    deriving (Monad, MonadState r, MonadState s) 

Trả lời

7

Bạn không thể có loại có hai phiên bản cho MonadState. Điều này là do MonadState được định nghĩa là

class Monad m => MonadState s m | m -> s where 
    get :: m s 
    set :: s -> m() 
    state :: (s -> (a, s)) -> m a 

Phần chính là | m -> s. Điều này yêu cầu phần mở rộng FunctionalDependencies và nêu rõ rằng đối với bất kỳ m nào, chúng tôi sẽ tự động biết số liên kết s. Điều này có nghĩa là đối với bất kỳ m nhất định nào, chỉ có thể là một lựa chọn cho s đó là hợp lệ. Vì vậy, bạn không thể làm việc này cho cả hai số MonadState r mMonadState s m trừ khi r ~ s. Nếu r ~ s, thì trình biên dịch sẽ biết trình đơn cơ bản nào để nó áp dụng? Trong trường hợp này, tôi nghĩ bạn cũng sẽ thấy rằng sẽ dễ hiểu hơn và làm việc với mã này nếu bạn tạo các hàm getput có hậu tố để chỉ ra, như getInner, setInnergetOuter, setOuter.

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