![](/img/trans.png)
[英]haskell — can one access type variables from an instance function declaration?
[英]Can one compose types in a Haskell instance declaration?
我已經編寫了一個Haskell類型類,使用(a -> m _)
形式的類型來聲明它的實例會很方便,其中m
是(* -> *)
,例如monad,而_
是保持不飽和的插槽。 我知道如何編寫新類型newtype X amb = X (a -> mb)
並聲明X am
的實例。 但是我正在尋找的是,如果可能的話,使用裸露的,未包裝的->
類型。
如果要聲明形式類型(a -> _)
實例,則可以這樣寫:
instance Foo a ((->) a) where ...
但我不知道如何/是否可以使用(a -> m _)
形式的類型。 我想我想在實例聲明中組成類型構造函數(->) a _
和類型構造函數m _
。
我想寫這樣的東西:
instance Foo a ((->) a (m :: *->*)) where ...
要么:
instance Foo a ((->) a (m *)) where ...
但是這些當然不起作用。 是否有可能做到這一點?
具體來說,這就是我要實現的目標。 我為MonadReaders編寫了一個類型類,該類型類嵌入在其他MonadReaders的內部(一個級別)中,如下所示:
{-# LANGUAGE FunctionalDependencies FlexibleInstances
UndecidableInstances #-}
class MonadReader w m => DeepMonadReader w r m | m -> r where
{ deepask :: m r
; deepask = deepreader id
; deeplocal :: (r -> r) -> m a -> m a
; deepreader :: (r -> a) -> m a
; deepreader f = do { r <- deepask; return (f r) }
}
instance MonadReader r m => DeepMonadReader w r (ReaderT w m) where
{ deepask = lift ask
; deeplocal = mapReaderT . local
; deepreader = lift . reader
}
最好還提供一個如下所示的實例:
instance MonadReader r m => DeepMonadReader w r ((->) w (m :: * ->
*)) where
{ deepask = \w -> ask
; deeplocal f xx = \w -> local f (xx w)
; deepreader xx = \w -> reader xx
}
我認為您走在錯誤的軌道上,並且使事情變得比他們需要的復雜得多。
一些觀察:
...((->)w(m :: *-> *))...
讓我們探究您的意思。 您正在將它用於DeepMonadReader
類中的類型參數m
,因此它必須是monad。 您能舉一個具有這種類型的單子的具體例子嗎? 為什么不只使用((->) w)
?
class MonadReader wm => DeepMonadReader wrm | m-> r哪里...
事實上, w
從未在任何成員的簽名apears是一個跡象表明有什么不妥。
...我為MonadReaders編寫了一個類型類,該類嵌入在其他MonadReaders的內部(一個級別)中...
我會采取相反的觀點。 談論monad堆棧是有意義的,它是另一個monad堆棧的轉換版本。 例如:
StateT s (WriterT w IO) "contains" IO
WriterT w (Maybe a) "contains" Maybe a
單子堆棧m1 “包含”另一個單子m2是什么意思? 這只是意味着有一種方法可以將m2中的計算轉換為m1中的計算:
convert :: m2 a -> m1 a
當然,使用monad變壓器時,這只是lift
。
為了表達您嵌入另一個monad中的monad閱讀器的概念,我將使用以下類型類:
class HasReader m m' r where ...
deepAsk :: m r
deepLocal :: (r -> r) -> m' a -> m a
這里的想法是,實例HasReader mm'r表示monad m “包含” monad m'的事實,而monad m'本身是具有環境r的閱讀器。
deepAsk返回M”,但在米計算環境。
deepLocal使用環境修改函數在m'中運行計算,但將其作為m中的計算返回。 請注意,此類型簽名與您的類型簽名有何不同:我的deepLocal使用不同的monad,分別為m'和m,而您的僅從m變為m 。
下一步是確定我們要為其編寫HasReader實例的三元組(m,m',r) 。 顯然,您似乎已經想到了這樣的實例:
m m' r
--------------------- ----------- --
ReaderT s (ReaderT r m) ReaderT r m r
ReaderT t (ReaderT s (ReaderT r m) ReaderT s (Reader T r m) s
...
但是要擁有這些實例似乎也很合理:
StateT s (ReaderT r m) ReaderT r m r
WriterT w (ReaderT r m) ReaderT r m r
MaybeT (ReaderT r m) ReaderT r m r
...
事實證明,在任何情況下我們都不需要HasReader類。 我們可以只寫表達,比如M計算”,並lift
它為m。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.