Это просто стандартный синтаксис записи. В таком определении типа, как
data Foo = Foo { a :: Int, b :: String }
, вероятно, вас не удивит, что мы автоматически получаем функции a :: Foo -> Int
и b :: Foo -> String
.
Для MaybeT
это абсолютно не отличается. (Он использует newtype
, а не data
, но здесь это не имеет значения, то же самое было бы, если бы вместо него использовалось определение data
)
newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }
это дает нам функцию runMaybeT :: MaybeT m a -> m (Maybe a)
по той же причине, по которой мы получаем функции a
и b
в более простом примере выше. Это просто то, что делает синтаксис записи.
В частности, в этом случае, как всегда с newtype
, определенным с использованием синтаксиса записи, функция runMaybeT
позволяет нам «развернуть» значение c монади, начиная с от абстрактного MaybeT m a
к более "конкретному" представлению как значение типа m (Maybe a)
.
Это используется в реализации >>=
для MaybeT m
: поскольку его первый аргумент (x
в вашем фрагменте) имеет тип MaybeT m a
, нам сначала нужно runMaybeT
, чтобы получить «развернутое» значение типа m (Maybe a)
, а затем использовать >>=
из «базовой монады» m
(показано здесь с do
обозначение), чтобы «извлечь» значение типа Maybe a
, которое затем сопоставляется с шаблоном обычным способом.