How to denote a Haskell static URI in code with Network.URI?

The Haskell Network.URI package has a function parseURI :: String -> Maybe URI .

I would like to have some static URIs in my code. Can I write the following?

 Just myURI = parseURI "http://google.com/" 

The "problem" is that if the URI string is actually garbled, it gets only at run time with a template failure.

I would like to avoid the tedious construction of a direct URI data type (which breaks the URI and makes it somewhat lose its conceptual meaning).

Is there a better way to have a static URI in the code and be more "secure"?

+6
source share
3 answers

How to use a Haskell pattern to check a static url using isURI at compile time? It is safe to use fromJust at run time when the URL must be valid.

For example, define staticURI like this.

 {-# LANGUAGE TemplateHaskell #-} module URI where import Data.Maybe (fromJust) import Network.URI (URI, isURI, parseURI) import Language.Haskell.TH (Q, TExp) staticURI :: String -> Q (TExp URI) staticURI uri | isURI uri = [|| fromJust $ parseURI uri ||] | otherwise = fail $ "Invalid URI: " ++ uri 

Then you can define your URL in other modules, for example.

 {-# LANGUAGE TemplateHaskell #-} import Network.URI (URI) import URI (staticURI) url :: URI url = $$(staticURI "http://www.google.com/") badUrl :: URI badUrl = $$(staticURI "http://www.google.com/##") 

When you pass the wrong url to staticURI , the compiler will throw an error.

 Invalid URI: http://www.google.com/## In the Template Haskell splice $$(staticURI "http://www.google.com/##") In the expression: $$(staticURI "http://www.google.com/##") In an equation for 'url': url = $$(staticURI "http://www.google.com/##") 
+6
source

Can I write the following?

No, do not map the template to Just unless you are sure that your URI is not distorted. A URI like this will give Nothing , resulting in a runtime error:

 λ> parseURI "http:/\\/google.com/" Nothing 

Instead, just specify a URI in the Maybe type and do your calculations using functions like fmap and others. Another way would be to check if it contains a valid URI using the isURI function or any other suitable function defined in Network.URI and then handle the relevant cases:

 λ> isURI "http:/\\/google.com/" False λ> isURI "http://google.com" True 
0
source

I recommend using the URI and URIAuth directly. You get a little more text, but also get a static guarantee that you really have a URI . But this is what you want to avoid :)

I would like to avoid the tedious construction of a direct URI data type (which breaks the URI and causes it to lose its conceptual meaning somewhat).

If you really use string literals, you can include OverloadedStrings and define an IsString instance for Maybe URI as follows:

 {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} import Data.String import Network.URI instance IsString (Maybe URI) where isString = parseURI someUri :: Maybe URI someUri = "http://google.ca" 

You cannot safely reset Maybe ; you just need to work with him.

0
source

Source: https://habr.com/ru/post/987620/


All Articles