Действительно ли возможно использовать синонимы типа в качестве аргументов конструктора типа преобразователей монады? В частности, если существует унарный синоним типа для прикладного преобразователя монады, он мог бы использоваться в качестве типа базовой монады в другом преобразователе монады?
Из того, что я вижу, что синонимы типа не приняты как первоклассные конструкторы типа, видят пример и сообщения об ошибках ниже:
-- Using type synonym of a monad transformer in another monad transformer.
import Control.Monad.Reader
-- inner transformer
type A a = ReaderT Int IO a
-- type B a = ReaderT String A a
{- Error:
readert2.hs:8:0:
Type synonym `A' should have 1 argument, but has been given 0
In the type synonym declaration for `B'
-}
-- type B a = ReaderT String (A a) a
{- Error:
readert2.hs:15:27:
Kind mis-match
The second argument of `ReaderT' should have kind `* -> *',
but `A a' has kind `*'
In the type `ReaderT String (A a) a'
In the type synonym declaration for `B'
-}
type B a = ReaderT String (ReaderT Int IO) a
{- OK -}
main = do
r <- flip runReaderT 39 $ do
n <- ask :: A Int
s <- flip runReaderT "foo" $ (ask :: B String)
return $ n + length s
print r
Есть ли способ постараться не разворачивать синоним типа A
в определении B a
?
Синонимы типа не могут быть частично применены. В этом конкретном случае вы можете написать
type A = ReaderT Int IO
type B a = ReaderT String A a
[или еще лучше type B = ReaderT String A
, чтобы использовать B
в другом монадном трансформаторе]
Вообще, трансформация невозможна без использования newtype/data, например:
type A a = Reader a Int
нельзя эквивалентно записать как type A = ....
. В некотором смысле, эта возможность была бы эквивалентна лямбде уровня типа \a -> Reader a Int