Can't match type Maybe vs not Maybe on Network.URI












1















Say I want to parse an environment variable, and default to localhost in its absence, using https://hackage.haskell.org/package/network-2.3/docs/Network-URI.html



I can write a function like so:



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


This works fine. Now let's say I want to handle errors. I note that parseURI returns a Maybe so ostensibly I just need to pattern match on that. So I create a custom Error:



data CustomError = MyCustomError Text deriving(Show)


I create a helper function:



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


Finally, I modify my initial function:



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


This fails to compile with:



• 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
|



And for the life of me I can't figure out why. If the initial implementation returns a Maybe, why is it converting to an unwrapper URI.URI which I can't then pass?



Crucially, when I change the pattern on parsedExtractor to expect a string, it also fails to compile with the inverse message (



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


I feel like I must be missing something completely fundamental. What is going on here?










share|improve this question

























  • I don't think that would be fine either. We can't bind a Maybe x with a function that wants a Maybe x as input - we should just call the function on the Maybe: parsedExtractor uri . URI.parseURI . toS $ uri

    – amalloy
    Nov 21 '18 at 9:16













  • apologies that's a syntax error I introduced in my experimentation. I've edited to the correct actual state (Which still errors)

    – Abraham P
    Nov 21 '18 at 9:17













  • @amalloy your suggestion worked! If you write it up as an answer (And maybe explain the issue!), I'll be very happy to accept it as an answer

    – Abraham P
    Nov 21 '18 at 9:30
















1















Say I want to parse an environment variable, and default to localhost in its absence, using https://hackage.haskell.org/package/network-2.3/docs/Network-URI.html



I can write a function like so:



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


This works fine. Now let's say I want to handle errors. I note that parseURI returns a Maybe so ostensibly I just need to pattern match on that. So I create a custom Error:



data CustomError = MyCustomError Text deriving(Show)


I create a helper function:



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


Finally, I modify my initial function:



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


This fails to compile with:



• 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
|



And for the life of me I can't figure out why. If the initial implementation returns a Maybe, why is it converting to an unwrapper URI.URI which I can't then pass?



Crucially, when I change the pattern on parsedExtractor to expect a string, it also fails to compile with the inverse message (



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


I feel like I must be missing something completely fundamental. What is going on here?










share|improve this question

























  • I don't think that would be fine either. We can't bind a Maybe x with a function that wants a Maybe x as input - we should just call the function on the Maybe: parsedExtractor uri . URI.parseURI . toS $ uri

    – amalloy
    Nov 21 '18 at 9:16













  • apologies that's a syntax error I introduced in my experimentation. I've edited to the correct actual state (Which still errors)

    – Abraham P
    Nov 21 '18 at 9:17













  • @amalloy your suggestion worked! If you write it up as an answer (And maybe explain the issue!), I'll be very happy to accept it as an answer

    – Abraham P
    Nov 21 '18 at 9:30














1












1








1








Say I want to parse an environment variable, and default to localhost in its absence, using https://hackage.haskell.org/package/network-2.3/docs/Network-URI.html



I can write a function like so:



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


This works fine. Now let's say I want to handle errors. I note that parseURI returns a Maybe so ostensibly I just need to pattern match on that. So I create a custom Error:



data CustomError = MyCustomError Text deriving(Show)


I create a helper function:



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


Finally, I modify my initial function:



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


This fails to compile with:



• 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
|



And for the life of me I can't figure out why. If the initial implementation returns a Maybe, why is it converting to an unwrapper URI.URI which I can't then pass?



Crucially, when I change the pattern on parsedExtractor to expect a string, it also fails to compile with the inverse message (



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


I feel like I must be missing something completely fundamental. What is going on here?










share|improve this question
















Say I want to parse an environment variable, and default to localhost in its absence, using https://hackage.haskell.org/package/network-2.3/docs/Network-URI.html



I can write a function like so:



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


This works fine. Now let's say I want to handle errors. I note that parseURI returns a Maybe so ostensibly I just need to pattern match on that. So I create a custom Error:



data CustomError = MyCustomError Text deriving(Show)


I create a helper function:



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


Finally, I modify my initial function:



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


This fails to compile with:



• 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
|



And for the life of me I can't figure out why. If the initial implementation returns a Maybe, why is it converting to an unwrapper URI.URI which I can't then pass?



Crucially, when I change the pattern on parsedExtractor to expect a string, it also fails to compile with the inverse message (



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


I feel like I must be missing something completely fundamental. What is going on here?







haskell types error-handling type-systems maybe






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 9:17







Abraham P

















asked Nov 21 '18 at 8:26









Abraham PAbraham P

7,01183894




7,01183894













  • I don't think that would be fine either. We can't bind a Maybe x with a function that wants a Maybe x as input - we should just call the function on the Maybe: parsedExtractor uri . URI.parseURI . toS $ uri

    – amalloy
    Nov 21 '18 at 9:16













  • apologies that's a syntax error I introduced in my experimentation. I've edited to the correct actual state (Which still errors)

    – Abraham P
    Nov 21 '18 at 9:17













  • @amalloy your suggestion worked! If you write it up as an answer (And maybe explain the issue!), I'll be very happy to accept it as an answer

    – Abraham P
    Nov 21 '18 at 9:30



















  • I don't think that would be fine either. We can't bind a Maybe x with a function that wants a Maybe x as input - we should just call the function on the Maybe: parsedExtractor uri . URI.parseURI . toS $ uri

    – amalloy
    Nov 21 '18 at 9:16













  • apologies that's a syntax error I introduced in my experimentation. I've edited to the correct actual state (Which still errors)

    – Abraham P
    Nov 21 '18 at 9:17













  • @amalloy your suggestion worked! If you write it up as an answer (And maybe explain the issue!), I'll be very happy to accept it as an answer

    – Abraham P
    Nov 21 '18 at 9:30

















I don't think that would be fine either. We can't bind a Maybe x with a function that wants a Maybe x as input - we should just call the function on the Maybe: parsedExtractor uri . URI.parseURI . toS $ uri

– amalloy
Nov 21 '18 at 9:16







I don't think that would be fine either. We can't bind a Maybe x with a function that wants a Maybe x as input - we should just call the function on the Maybe: parsedExtractor uri . URI.parseURI . toS $ uri

– amalloy
Nov 21 '18 at 9:16















apologies that's a syntax error I introduced in my experimentation. I've edited to the correct actual state (Which still errors)

– Abraham P
Nov 21 '18 at 9:17







apologies that's a syntax error I introduced in my experimentation. I've edited to the correct actual state (Which still errors)

– Abraham P
Nov 21 '18 at 9:17















@amalloy your suggestion worked! If you write it up as an answer (And maybe explain the issue!), I'll be very happy to accept it as an answer

– Abraham P
Nov 21 '18 at 9:30





@amalloy your suggestion worked! If you write it up as an answer (And maybe explain the issue!), I'll be very happy to accept it as an answer

– Abraham P
Nov 21 '18 at 9:30












1 Answer
1






active

oldest

votes


















5















And for the life of me I can't figure out why. If the initial
implementation returns a Maybe, why is it converting to an unwrapper
URI.URI which I can't then pass?




To refer the definition of >>= from Control.Monad, it has type signture:



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


Now, compare to the expression:



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


We have:



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


Since (URI.parseURI . toS) uri return type Maybe URI.URI and Maybe is an instance of Monad, so



m a ~ Maybe URI.URI 


and



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


and m b can be infered to m (URI.URI), so the function (i.e. parsedExtractor uri) after >>= expected to has type as:



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


But actual is not.






share|improve this answer





















  • 3





    Note that the typical notation for type equality uses ~, not =. So I would write, for example, (URI.parseURI . toS) uri :: Maybe URI.URI ~ m a.

    – amalloy
    Nov 21 '18 at 10:19











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53407890%2fcant-match-type-maybe-vs-not-maybe-on-network-uri%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









5















And for the life of me I can't figure out why. If the initial
implementation returns a Maybe, why is it converting to an unwrapper
URI.URI which I can't then pass?




To refer the definition of >>= from Control.Monad, it has type signture:



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


Now, compare to the expression:



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


We have:



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


Since (URI.parseURI . toS) uri return type Maybe URI.URI and Maybe is an instance of Monad, so



m a ~ Maybe URI.URI 


and



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


and m b can be infered to m (URI.URI), so the function (i.e. parsedExtractor uri) after >>= expected to has type as:



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


But actual is not.






share|improve this answer





















  • 3





    Note that the typical notation for type equality uses ~, not =. So I would write, for example, (URI.parseURI . toS) uri :: Maybe URI.URI ~ m a.

    – amalloy
    Nov 21 '18 at 10:19
















5















And for the life of me I can't figure out why. If the initial
implementation returns a Maybe, why is it converting to an unwrapper
URI.URI which I can't then pass?




To refer the definition of >>= from Control.Monad, it has type signture:



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


Now, compare to the expression:



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


We have:



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


Since (URI.parseURI . toS) uri return type Maybe URI.URI and Maybe is an instance of Monad, so



m a ~ Maybe URI.URI 


and



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


and m b can be infered to m (URI.URI), so the function (i.e. parsedExtractor uri) after >>= expected to has type as:



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


But actual is not.






share|improve this answer





















  • 3





    Note that the typical notation for type equality uses ~, not =. So I would write, for example, (URI.parseURI . toS) uri :: Maybe URI.URI ~ m a.

    – amalloy
    Nov 21 '18 at 10:19














5












5








5








And for the life of me I can't figure out why. If the initial
implementation returns a Maybe, why is it converting to an unwrapper
URI.URI which I can't then pass?




To refer the definition of >>= from Control.Monad, it has type signture:



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


Now, compare to the expression:



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


We have:



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


Since (URI.parseURI . toS) uri return type Maybe URI.URI and Maybe is an instance of Monad, so



m a ~ Maybe URI.URI 


and



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


and m b can be infered to m (URI.URI), so the function (i.e. parsedExtractor uri) after >>= expected to has type as:



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


But actual is not.






share|improve this answer
















And for the life of me I can't figure out why. If the initial
implementation returns a Maybe, why is it converting to an unwrapper
URI.URI which I can't then pass?




To refer the definition of >>= from Control.Monad, it has type signture:



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


Now, compare to the expression:



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


We have:



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


Since (URI.parseURI . toS) uri return type Maybe URI.URI and Maybe is an instance of Monad, so



m a ~ Maybe URI.URI 


and



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


and m b can be infered to m (URI.URI), so the function (i.e. parsedExtractor uri) after >>= expected to has type as:



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


But actual is not.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 21 '18 at 13:36

























answered Nov 21 '18 at 10:16









assembly.jcassembly.jc

2,1041215




2,1041215








  • 3





    Note that the typical notation for type equality uses ~, not =. So I would write, for example, (URI.parseURI . toS) uri :: Maybe URI.URI ~ m a.

    – amalloy
    Nov 21 '18 at 10:19














  • 3





    Note that the typical notation for type equality uses ~, not =. So I would write, for example, (URI.parseURI . toS) uri :: Maybe URI.URI ~ m a.

    – amalloy
    Nov 21 '18 at 10:19








3




3





Note that the typical notation for type equality uses ~, not =. So I would write, for example, (URI.parseURI . toS) uri :: Maybe URI.URI ~ m a.

– amalloy
Nov 21 '18 at 10:19





Note that the typical notation for type equality uses ~, not =. So I would write, for example, (URI.parseURI . toS) uri :: Maybe URI.URI ~ m a.

– amalloy
Nov 21 '18 at 10:19




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53407890%2fcant-match-type-maybe-vs-not-maybe-on-network-uri%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Guess what letter conforming each word

Port of Spain

Run scheduled task as local user group (not BUILTIN)