簡體   English   中英

一個Haskell實例聲明中可以組成類型嗎?

[英]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”,但在計算環境。

deepLo​​cal使用環境修改函數在m'中運行計算,但將其作為m中的計算返回。 請注意,此類型簽名與您的類型簽名有何不同:我的deepLo​​cal使用不同的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM