Warning: Pattern match(es) are overlapped when matching on strings - haskell

I am trying to make a simple url route in Haskell and can't get around the warning:
Warning: Pattern match(es) are overlapped
In a case alternative: "/" -> ...
Ok, modules loaded: Main.
the snippet:
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.Wai.Handler.Warp (run)
import Network.Wai.Middleware.Debug (debug)
import Network.HTTP.Types (statusOK, status404)
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import Data.ByteString.Char8 (unpack)
import Data.ByteString.Lazy.Char8 (pack)
import qualified Data.Text.Lazy as T
import Control.Monad.IO.Class (liftIO, MonadIO)
application req = do
case unpack $ rawPathInfo req of
"/items" -> itemsJSON
"/" -> indexPage
_ -> return $ responseLBS status404 [("Content-Type", "text/plain")]
"Not found"
indexPage = do
page <- liftIO $ L.readFile "templates/index.html"
return $ responseLBS statusOK [("Content-Type", "text/html; charset=utf-8")] page
itemsJSON =
return $ responseLBS statusOK
[("Content-Type", "application/json; charset=utf-8")] "hi"
main = do
run 3000 $ debug $ application
UPD:
replaced snippet with complete program, and
$ ghc -V
The Glorious Glasgow Haskell Compilation System, version 6.12.1

This is a bug, and is fixed in newer versions of GHC.

Related

How to import libraries or the prelude into the context in which GHC.runGhc runs

I'm trying to evaluate some dynamic code with GHC.dynCompileExpr, as below.
module Main where
import Data.Dynamic
import GHC
import GHC.Paths as GHP
import GHC.Types
import GHC.Prim
import GHC.Num
main :: IO ()
main = do
dynval <- GHC.runGhc (Just GHP.libdir) $ do
setSessionDynFlags =<< getSessionDynFlags
GHC.dynCompileExpr "[3,2,4,0]::Integer"
let val = fromDynamic dynval :: Maybe [Integer]
putStrLn $ show val
When I run it, however, it fails with the error: Not in scope: type constructor or class ‘Integer’. It seems in the context in which GHC.dynCompileExpr runs, no libraries are available, not even the prelude. How would I go about importing a library or the prelude into this context? Including an import statement in GHC.dynCompileExpr just results in a parse error.
this took me a while to figure out, but I seem to have found a way to get it to work.
module Main where
import Data.Dynamic
import GHC
import GHC.Paths ( libdir )
import GHC.Types
import GHC.Prim
import GHC.Num
import DynFlags
main :: IO ()
main = do
dynval <- GHC.runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
setSessionDynFlags dflags
setContext [ IIDecl $ simpleImportDecl (mkModuleName "Prelude") ]
GHC.dynCompileExpr "[3, 2, 1, 0] :: [Prelude.Integer]"
let val = fromDynamic dynval :: Maybe [Integer]
putStrLn $ show val
The solution seems to be in the following line:
setContext [ IIDecl $ simpleImportDecl (mkModuleName "Prelude") ]
This brings Prelude into context and the expression is evaluated correctly, giving the output:
Just [3,2,1,0]
I got this code from here. I hope this helps!

Unable to create a custom header to use it in "withManager"

I can't create a custom header without using OverloadedStrings
import Data.Aeson
import qualified Data.ByteString.Lazy as B
import Network.HTTP.Conduit
import qualified Network.HTTP.Headers as HHeaders
import qualified Network.HTTP.Types as HTypes
import qualified Data.ByteString.Char8 as C8
import qualified Data.ByteString.Lazy.Char8 as LC8
-- myHeader1 = (HHeaders.HdrAccept $ C8.pack "some data")
myHeader1 = HHeaders.mkHeader HHeaders.HdrAccept "some data"
get :: String -> IO (Response LC8.ByteString)
get url1 = do
req1 <- parseUrl url1
res1 <- withManager $ httpLbs req1 { method = HTypes.methodGet, requestHeaders = [myHeader1] }
return res1
An error:
Couldn't match type ‘HHeaders.Header’
with ‘(HTypes.HeaderName, C8.ByteString)’
Expected type: HTypes.Header
Actual type: HHeaders.Header
In the expression: myHeader1
In the ‘requestHeaders’ field of a record
What am I doing wrong?
Network.HTTP.Conduit and Network.HTTP.Headers are from incompatible HTTP libraries. Request headers for http-conduit/http-client can be created using the http-types library:
import Data.Aeson
import qualified Data.ByteString.Lazy as B
import Network.HTTP.Conduit as HHeaders
import qualified Network.HTTP.Types as HTypes
import qualified Data.ByteString.Char8 as C8
import qualified Data.ByteString.Lazy.Char8 as LC8
myHeader1 = (HTypes.hAccept, C8.pack "some data")
get :: String -> IO (Response LC8.ByteString)
get url1 = do
req1 <- parseUrl "some url"
res1 <- withManager $ httpLbs req1 { method = HTypes.methodGet, requestHeaders = [myHeader1] }
return res1
To clarify:
You were importing Network.HTTP.Headers from the HTTP library. Although the imports look similar, this is a self-contained library which defines it's own header types and not intended to be used with http-types.
http-client is compatible with the http-types. If you follow the definition for RequestHeader it will lead you to http-types.
In the future, one way to check the compatibility of orthogonal libraries is to look at the build depends on the Hackage index or follow the types as far as possible.

how to get html from blaze -- print to file

I am working through the blaze-html tutorial. I just want a simple Hello World page.
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad (forM_)
import Text.Blaze.Html5
import Text.Blaze.Html5.Attributes
import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as A
import Text.Blaze.Html.Renderer.Text
notes :: Html
notes = docTypeHtml $ do
H.head $ do
H.title "John´ s Page"
body $ do
p "Hello World!"
Where is it? How do I get my HTML? Can I just print it to the terminal or a file? That would be a great start.
<html>
<head><title>John's Page</title></head>
<body><p>Hello World!</p></body>
</html>
And are all the import statements really necessary? I just want it to work.
I tried printing using the renderHTML function but I just get an error message:
main = (renderHtml notes) >>= putStrLn
notes.hs:21:9:
Couldn't match expected type `IO String'
with actual type `Data.Text.Internal.Lazy.Text'
In the return type of a call of `renderHtml'
In the first argument of `(>>=)', namely `(renderHtml notes)'
In the expression: (renderHtml notes) >>= putStrLn
The result of "renderHtml" is not wrapped in a monad so you don't need to use >>=
Just print out the result:
main = putStrLn $ show $ renderHtml notes
The result is:
"<!DOCTYPE HTML>\n<html><head><title>John' s
Page</title></head><body><p>Hello World!</p></body></html>"
Generally speaking, the place to start with errors like this is to load the file into GHCI and see what the types are. Here is the session I'd use for this issue:
*Main> :t notes
notes :: Html
*Main> :t renderHtml notes
renderHtml notes :: Data.Text.Internal.Lazy.Text
You can see that the output of renderHtml notes is just an instance of Text. Text has a Show instance so we can just call "putStrLn $ show $ renderHtml notes" to get the desired output.
However, it is usually better to use the Data.Text.[Lazy.]IO package to perform IO when using Text. Note the import for "TIO" and the last line in the code below:
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad (forM_)
import Text.Blaze.Html5
import Text.Blaze.Html5.Attributes
import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as A
import Text.Blaze.Html.Renderer.Text
import qualified Data.Text.Lazy.IO as TIO
notes :: Html
notes = docTypeHtml $ do
H.head $ do
H.title "John' s Page"
body $ do
p "Hello World!"
--main = putStrLn $ show $ renderHtml notes
main = TIO.putStr $ renderHtml notes

Haskell Aeson destructuring generic parse

I have a JSON request in the style of
{"command":"get","params":{"something":"something else"}}
and this code snippet from the Yesod book
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai (Response, responseLBS, Application, requestBody)
import Network.HTTP.Types (status200, status400)
import Network.Wai.Handler.Warp (run)
import Data.Aeson.Parser (json)
import Data.Conduit.Attoparsec (sinkParser)
import Control.Monad.IO.Class (liftIO)
import Data.Aeson (Value(..), encode, object, (.=))
import Control.Exception (SomeException)
import Data.ByteString (ByteString)
import Data.Conduit (ResourceT, ($$))
import Control.Exception.Lifted (handle)
main :: IO ()
main = run 3000 app
app :: Application
app req = handle invalidJson $ do
value <- requestBody req $$ sinkParser json
newValue <- liftIO $ modValue value
return $ responseLBS
status200
[("Content-Type", "application/json")]
$ encode newValue
invalidJson :: SomeException -> ResourceT IO Response
invalidJson ex = return $ responseLBS
status400
[("Content-Type", "application/json")]
$ encode $ object
[ ("message" .= show ex)
]
-- Application-specific logic would go here.
modValue :: Value -> IO Value
modValue (Object o)
| -- key "command" corresponds to value "get"
| otherwise = fail "Invalid command"
But I can't wrap my head around how I would destructure the generated Value data structure. How do I go about getting the values of keys etc. I realise I could parse to an explicitly defined data structure, but that would bring other kinds of problems to my use case.
In modValue I've put a comment where I can't figure out what to put. I tried treating it as a Map, since that's how it is implemented inside Aeson, but that obviously doesn't type check.
EDIT:
Adding Data.HashMap to imports and using the line
| M.lookup "command" o == Just "get" = return $ object [("result" .= (String "YAY"))]
gives the following error message.
main.hs:39:26:
Couldn't match expected type `M.Map k0 a0'
with actual type `aeson-0.6.0.2:Data.Aeson.Types.Internal.Object'
In the second argument of `M.lookup', namely `o'
In the first argument of `(==)', namely `M.lookup "command" o'
In the expression: M.lookup "command" o == Just "get"
EDIT2:
On a sudden hunch, I tracked down an error message I got earlier involving "unordered-containers". This is the package that Aeson uses. But I realised that I also had the package hashmap installed, which is imported as Data.HashMap. The hashmaps from unordered-containers are imported as Data.HashMap.Strict or Lazy!
Changing the line import qualified Data.HashMap as M to import qualified Data.HashMap.Strict as M fixed it anyway. Now the given answer works!
Since an aeson JSON object is a Hashmap, you can use the Hasmap interface, in this case lookup.
import qualified Data.HashMap.Strict as M
M.lookup "command" o == Just "get"

Haskell. Problem with WAI simple web app (unpacking bytestrings)

Did lot of packing, unpacking and etc playing with Strings and Texts and still stuck,
the goal is simple as hello world with extra request info concatenated:
{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.Wai.Handler.Warp (run)
import Network.HTTP.Types (statusOK)
import qualified Data.ByteString.Lazy as L
import Data.ByteString.Char8 (unpack)
import qualified Data.Text.Lazy as T
application req = do
return $ responseLBS statusOK [("Content-Type", "text/plain")]
$ L.pack $ "Hello World" ++ (unpack $ rawPathInfo req)
main = run 3000 application
produces:
Couldn't match expected type `GHC.Word.Word8'
against inferred type `Char'
Expected type: [GHC.Word.Word8]
Inferred type: [Char]
In the second argument of `(++)', namely
`(unpack $ rawPathInfo req)'
In the second argument of `($)', namely
`"Hello World" ++ (unpack $ rawPathInfo req)
Eagerly need hint how to make it work.
Use Data.ByteString.Lazy.Char8.pack instead of L.pack.
That's a lot of packing and unpacking. I don't have wai installed, so I can't test, but something like this should be simpler:
application req = do
return $ responseLBS statusOK [("Content-Type", "text/plain")]
$ L.append "Hello World" $ rawPathInfo req
i.e. simply use ByteString's append rather than String's (++).

Resources