Не может соответствовать типу Может быть против не Может быть в сети.URI - PullRequest
0 голосов
/ 21 ноября 2018

Скажем, я хочу проанализировать переменную окружения и по умолчанию использовать localhost при ее отсутствии, используя https://hackage.haskell.org/package/network-2.3/docs/Network-URI.html

. Я могу написать такую ​​функцию:

parseRabbitURI :: Text -> Maybe URI.URI
parseRabbitURI "" = URI.parseURI "amqp://guest:guest@127.0.0.1/"
parseRabbitURI uri = (URI.parseURI . toS) uri

Это работает нормально,Теперь скажем, я хочу обрабатывать ошибки.Я отмечаю, что parseURI возвращает Maybe, так что якобы мне просто нужно сопоставить шаблон с этим.Поэтому я создаю пользовательскую ошибку:

data CustomError = MyCustomError Text deriving(Show)

Я создаю вспомогательную функцию:

parsedExtractor
  :: MonadError CustomError.MyCustomError m
  => Text
  -> Maybe URI.URI
  -> m(URI.URI)
parsedExtractor originalString Nothing = throwError $ FlockErrors.FailedToParseURI originalString
parsedExtractor _ (Just uri) = do
  pure uri

Наконец, я изменяю свою начальную функцию:

parseRabbitURI :: MonadError CustomError.MyCustomError m => Text -> m(URI.URI)
parseRabbitURI "" = URI.parseURI "amqp://guest:guest@127.0.0.1/" >>= parsedExtractor "amqp://guest:guest@127.0.0.1/"
parseRabbitURI uri = (URI.parseURI . toS) uri >>= parsedExtractor uri

Это не удаетсяскомпилировать с:

• Couldn't match type ‘URI.URI’ with ‘Maybe URI.URI’
  Expected type: URI.URI -> Maybe URI.URI
    Actual type: Maybe URI.URI -> Maybe URI.URI
• In the second argument of ‘(>>=)’, namely ‘parsedExtractor uri’
  In the expression: (URI.parseURI . toS) uri >>= parsedExtractor uri
  In an equation for ‘parseRabbitURI’:
      parseRabbitURI uri
        = (URI.parseURI . toS) uri >>= parsedExtractor uri

|23 |parseRabbitURI uri = (URI.parseURI. toS) uri >> = parsedExtractor uri |

И по жизни я не могу понять, почему.Если первоначальная реализация возвращает значение Maybe, почему оно конвертируется в URI.URI для развертывания, который я не могу затем передать?

Важно, когда я изменяю шаблон на parsedExtractor, ожидая строку, это также не компилируется с обратным сообщением (

Couldn't match expected type ‘URI.URI’
                      with actual type ‘Maybe URI.URI’

Мне кажется, что я упускаю что-то совершенно фундаментальное. Что здесь происходит?

1 Ответ

0 голосов
/ 21 ноября 2018

И по жизни я не могу понять, почему.Если первоначальная реализация возвращает значение Maybe, почему оно конвертируется в URI.URI для развертывания, который я не могу затем передать?

Чтобы сослаться на определение >>= из Control.Monad, он имеет тип signture:

(>>=) :: m a -> (a -> m b) -> m b

Теперь, сравните с выражением:

(URI.parseURI . toS) uri >>= parsedExtractor uri

У нас есть:

m a        ~ (URI.parseURI . toS) uri
(a -> m b) ~ parsedExtractor uri

Так как (URI.parseURI . toS) uriвозвращаемый тип Maybe URI.URI и Maybe является экземпляром Monad, поэтому

m a ~ Maybe URI.URI 

и

(a -> m b) ~ (URI.URI -> m b) 

и m b могут быть выведены в m (URI.URI), поэтомуфункция (то есть parsedExtractor uri) после >>=, как ожидается, будет иметь тип:

(URI.URI -> m (URI.URI))

Но фактическим не является.

...