Безопасно ли получать MonadThrow, MonadCatch, MonadBaseControl, MonadUnliftIO и т. Д.? - PullRequest
1 голос
/ 03 июля 2019

Я рефакторинг некоторого старого кода, который находится в полиморфном, но ограниченном классе типов, монаде:

class ( MonadIO m
      , MonadLogger m
      , MonadLoggerIO m
      , MonadThrow m
      , MonadCatch m
      , MonadMask m
      , MonadBaseControl IO m
      , MonadUnliftIO) => HasLogging m where

В старом коде основной монадой приложения была ...

type AppM = ReaderT Env IO

... который теперь изменится на ...

newtype AppM (features :: [FeatureFlag]) a = AppM (ReaderT Env IO a)
  deriving (Functor, Applicative, Monad, MonadReader Env, MonadIO)

Учитывая этот контекст, безопасно ли автоматически получать следующее:

  • MonadThrow
  • MonadCatch
  • MonadMask
  • MonadBaseControl
  • MonadUliftIO

Не вдаваясь во внутренности GHC, как лучше всего развить интуицию о том, что на самом деле происходит, когда компилятор получает вещи автоматически?

1 Ответ

1 голос
/ 03 июля 2019

В руководстве пользователя есть документация по каждому расширению, и оно постоянно улучшается;вот раздел о деривации, которого должно быть достаточно, чтобы знать, что на самом деле происходит: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#extensions-to-the-deriving-mechanism

В этом случае все эти классы обрабатываются как GeneralizedNewtypeDeriving.

{-# LANGUAGE GeneralizedNewtypeDeriving, UndecidableInstances #-}

module M where

import Control.Monad.IO.Unlift
import Control.Monad.Catch
import Control.Monad.Trans.Control
import Control.Monad.Base
import Control.Monad.Reader

newtype Foo a = Foo (ReaderT () IO a)
  deriving (Functor, Applicative, Monad, MonadIO, MonadUnliftIO, MonadThrow, MonadCatch, MonadMask, MonadBase IO, MonadBaseControl IO)

В общемтри соответствующих расширения для пользовательских классов: GeneralizedNewtypeDeriving, DerivingVia и DeriveAnyType.И также стоит включить DerivingStrategies, чтобы сделать его явным, который используется.

...