1
我使用ProgramT從業務包待辦事項GADTs打破等式推理哈斯克爾
{-# LANGUAGE GADTs #-}
import Control.Monad ((<=<))
import Control.Monad.Operational
data Motor' a where
--Define GADT
serialNewportT :: (Monad m, MonadIO m) => ProgramT Motor' m a -> m a
serialNewportT = eval <=< viewT
where
eval :: (Monad m, MonadIO m) => ProgramViewT Motor' m v -> m v
eval (Return x) = return x
eval (x :>>= k) = f x >>= serialNewportT . k
f :: (Monad m, MonadIO m) => Motor' a -> m a
f = undefined -- excluded for brevity
代碼如下解釋,因爲它的立場,目前類型檢查就好了。但是,我希望能夠切換解釋器如何處理不同的電機,所以我想使f
成爲一個參數,而不是硬編碼。我嘗試使用以下代碼進行此開關:
{-# LANGUAGE GADTs #-}
import Control.Monad ((<=<))
import Control.Monad.Operational
data Motor' a where
--Define GADT
serialNewportT :: (Monad m, MonadIO m) => (Motor' a -> m a) -> ProgramT Motor' m a -> m a
serialNewportT f = eval <=< viewT
where
eval :: (Monad m, MonadIO m) => ProgramViewT Motor' m v -> m v
eval (Return x) = return x
eval (x :>>= k) = f x >>= serialNewportT f . k
但是,此代碼失敗,出現錯誤消息
Couldn't match type ‘b’ with ‘c’
‘b’ is a rigid type variable bound by
a pattern with constructor
:>>= :: forall (instr :: * -> *) (m :: * -> *) a b.
instr b -> (b -> ProgramT instr m a) -> ProgramViewT instr m a,
in an equation for ‘eval’
‘c’ is a rigid type variable bound by
the type signature for
serialNewportT :: (Monad m, MonadIO m) =>
(Motor' c -> m c) -> ProgramT Motor' m a -> m a
Expected type: Motor' c
Actual type: Motor' b
因爲我只是與同類型的局部更換一個全球的名字,我還以爲它應該順利工作過。我怎樣才能得到類型與f
作爲一個參數統一?
您沒有正確翻譯F'的'類型。在原始代碼中,它可以通過類型'Motor'a'對任何'a'實例化,但是在非工作代碼中,您聲明它的類型與'ProgramT Motor'中的'a'完全相同。 ,而在函數體中,你可以在'Motor'b'上調用'f'來尋找其他的(存在量化的)類型'b'。您可能只需要更高的排名類型:'serialNewportT ::(Monad m,MonadIO m)=>(全部x。Motor'x - > mx) - > ProgramT Motor'ma - > ma' – user2407038
@ user2407038似乎是一個答案給我 – Carsten
呃。我對範圍類型變量進行了大量研究,試圖讓所有內容匹配,但沒有考慮N級類型。我想現在該是最後學習的時候了。 @ user2407038,如果你想讓這個答案,我會給你信貸。 – user640078