Missing data constructor HostAny in Haskell - haskell

I am experimenting with Conduit Network and I cannot compile this code because it is cannot find the data constructor: HostAny
conduit-extra is installed so I am very puzzled why it cannot find it?
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Conduit
import Data.Conduit.Network
serverApp :: AppData -> IO ()
serverApp d = do appSource d $$ appSink d
main :: IO()
main = runTCPServer (serverSettings 8900 HostAny) serverApp
Here's the GHC error:
pez#devbox:~/dev$ runhaskell server.hs
server.hs:10:42: Not in scope: data constructor `HostAny'

If you look at the documentation for conduit-extras, you'll see
data HostPreference
Which host to bind.
Note: The IsString instance recognizes the following special values:
* means HostAny
*4 means HostIPv4
!4 means HostIPv4Only
*6 means HostIPv6
!6 means HostIPv6Only
Which tells me that you should be using the extension OverloadedStrings and then you can just write your code as
main = runTCPServer (serverSettings 8900 "*") serverApp
Although I have to say that is a strange API this library has chosen. I personally would much rather have the ability to use IsString or an explicit constructor in cases where I don't want to use OverloadedStrings for whatever reason.

Related

Evaluation of template haskell in Yesod

While going through the examples of the Yesod Book, I'm running into an issue with the following snippet:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
import Data.Text (Text)
import qualified Data.Text as T
import Yesod
data App = App
instance Yesod App
mkYesod "App" [parseRoutes|
/person/#Text PersonR GET
/year/#Integer/month/#Text/day/#Int DateR
/wiki/*Texts WikiR GET
|]
getPersonR :: Text -> Handler Html
getPersonR name = defaultLayout [whamlet|<h1>Hello #{name}!|]
handleDateR :: Integer -> Text -> Int -> Handler Text -- text/plain
handleDateR year month day =
return $
T.concat [month, " ", T.pack $ show day, ", ", T.pack $ show year]
getWikiR :: [Text] -> Handler Text
getWikiR = return . T.unwords
main :: IO ()
main = warp 3000 App
(It's on page 124 of 598; route arguments)
The instance declaration on line 11 raises the following error:
YesodRouteParams.hs:11:10: error:
• No instance for (RenderRoute App)
arising from the superclasses of an instance declaration
• In the instance declaration for ‘Yesod App’
|
11 | instance Yesod App
|
It can be fixed by moving that line below the mkYesod block, where routes are defined.
I'm trying to understand why that is. Does it mean that Template Haskell evaluation at compile time happens simultaneously with the written code evaluation?
I ask because in Crystal, for example, macros are expanded before anything else. So the order of things doesn't really matter in a file (or app). But by the looks of it, they do in Haskell. Or is there another explanation?
This was because of a change made in GHC 9.0.1. From the release notes:
Breaking change: Template Haskell splices now act as separation points between constraint solving passes. It is no longer possible to use an instance of a class before a splice and define that instance after a splice. For example, this code now reports a missing instance for C Bool:
class C a where foo :: a
bar :: Bool
bar = foo
$(return [])
instance C Bool where foo = True
If you were to downgrade to GHC 8.10.7, you'd see that your code would then work as you wrote it.
I opened https://github.com/yesodweb/yesodweb.com-content/pull/269 to fix the examples in the book.

How to get haskell compiler version within code without a long list of CPP if/else conditionals?

Something along the lines of:
import GHC.Version qualified
main :: IO ()
main = print $ GHC.Version.current
-- would print Version 8 10 7
A roundabout way is to execute ghc --version from shell:
import System.Process
main = system "ghc --version"
but this may be incorrect when the running GHC isn't the same as the ghc in PATH.
Yes, in two ways. The first using System.Info.compilerVersion
import System.Info
main :: IO ()
main = print compilerVersion
-- prints "Version {versionBranch = [8,6], versionTags = []}"
Second via the CPP language extension:
{-# LANGUAGE CPP #-}
main :: IO ()
main = print __GLASGOW_HASKELL__
-- prints "806" (of type Integer)
Docs on how that number has been come up with.

How does one use an instance function in Haskell when ghc complains it is not in scope, despite imports?

In A Gentle Introduction to Haskell, Version 98, it is said:
Instance declarations are not explicitly named in import or export
lists. Every module exports all of its instance declarations and every
import brings all instance declarations into scope.
This seems like good sense to me. Anyhow, when I try this for fromNumber from the FromNumber PixelFormat Word32 instance, I'm met with the error:
/home/brandon/workspace/hico/src/Hico/Game.hs:269:50: error:
Variable not in scope:
fromNumber :: Word32 -> SDL.Video.Renderer.PixelFormat
|
269 | let pixFmt :: SDL.Video.Renderer.PixelFormat = fromNumber rawPixFmt
|
The type in the error message looks correct to me. My relevant imports are:
import qualified SDL as SDL
import qualified SDL.Font
import qualified SDL.Image
import qualified SDL.Internal.Types (Window(..))
import qualified SDL.Raw
import SDL.Raw.Video (getWindowPixelFormat)
import qualified SDL.Video.Renderer
(especially the last line with import qualified SDL.Video.Renderer).
Out of a sense of paranoia, and since I had already a local copy of sdl2 handy, I modified the code in SDL2's Renderer.hs and added the below changes, which happily compiled, but shows that is not where the problem is:
{-# LANGUAGE InstanceSigs #-}
-- omitted ...
fromNumber :: Word32 -> PixelFormat
fromNumber n' = case n' of -- ommited ...
I have a feeling I'm once again doing something stupid with imports, though I'm not sure.
Instances are global, but the class itself and its methods are not. So if you have
module X () where
instance Foo Bar where fooBar = undefined
and import X, then you will be able to pass Bars into functions which demand their arguments be instance of Foo (or get Bars back from things that promise to produce an instance of Foo) -- but will not be able to name Foo, Bar, or fooBar yourself unless you've imported those from elsewhere!
The fix in your case is to find a module which exports fromNumber, e.g. by exporting FromNumber(..), and import it from there.

LiftIO, do block, and syntax

I'm getting to grips with writing an API in Haskell using Scotty. My files are provided below. My questions are:
In the routes definition, I'm extracting from liftIO whatsTheTime in a do block. This works, but it seems verbose. Is there a nicer syntax?
In the whatsTheTime definition, I'm needing to do fromString. I'd have thought OverloadedString would take care of that, but that's not the case. I'd really appreciate it if somebody pointed out why it doesn't work without fromString.
In a stack project, if I need a directive like OverloadedStrings, do I need to include it every file that needs it, or just at the top of the main entrypoint?
Api.hs:
{-# LANGUAGE OverloadedStrings #-}
module Api
( whatsTheTime
) where
import Data.Time (getCurrentTime)
import Web.Scotty
import Data.String
whatsTheTime :: IO (ActionM ())
whatsTheTime = do
time <- getCurrentTime
return $ text $ fromString ("The time is now " ++ show time)
Main.hs:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
module Main where
import Api
import Web.Scotty
import Control.Monad.IO.Class
routes = do
get "/" $ do
res <- liftIO whatsTheTime
res
main :: IO ()
main = do
putStrLn "Starting server..."
scotty 3000 routes
(1) This:
do
res <- liftIO whatsTheTime
res
Desugars to this:
liftIO whatsTheTime >>= \ res -> res
If you look at the type of \ m -> m >>= id:
(Monad m) => m (m a) -> m a
That’s exactly the type of join (Hoogle), so you can use:
get "/" $ join $ liftIO whatsTheTime
join is a common idiom for “execute this action which returns an action, and also execute the returned action”.
(2) OverloadedStrings is for overloading of string literals. You have an overloaded literal "The time is now ", but you constrain it to be of type String by using it as an operand of (++) with a String (the result of show time). You can pack the result of show time as a Text instead using fromString or Data.Text.pack:
import Data.Monoid ((<>))
import qualified Data.Text as Text
-- ...
return $ text $ "The time is now " <> Text.pack (show time)
(3) LANGUAGE pragmas operate per file; as #mgsloan notes, you can add OverloadedStrings to the default-extensions: field of your library or executable in your .cabal file.

Can a quasiquoter 'use' variables defined in the same file it is called?

So, I'm starting to experiment with quasiquotation and template haskell.
I want to modify an existing (large) quasiquotation code, while using the actual value of a variable defined where it is 'called'. To illustrate with a simple example:
main.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Exp02
x = "cde"
main = do
putStrLn [str|$x|]
Exp02.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
module Exp02 where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Quote
xpto :: String -> ExpQ
xpto [] = stringE []
xpto ('$':rest) = varE (mkName rest)
xpto str = stringE str
str = QuasiQuoter
{ quoteExp = xpto
, quotePat = fail $ "patterns"
, quoteType= fail $ "types"
, quoteDec = fail $ "declarations"
}
While this compiles and prints out "cde", this is not what I want. My understanding is that the resulting code in main after splicing is: putStrLn x. What I want is to generate putStrLn cde (I know this is not valid haskell code, but it's just to represent my point).
Thus, to put it in another way, I do not want to 'create a reference to the variable x in the main file', I want to actually use its value inside the xpto quasiquoter code.
I am guessing this may not be possible, since it would imply a circular reference between main.hs and Exp02.hs, and thus face the TH stage restriction. Is this correct, or is there a way to use x value inside the xpto code?
Thanks!
No, what you are trying to do isn't currently possible. From the template haskell docs:
You can only run a function at compile time if it is imported from another module that is not part of a mutually-recursive group of modules that includes the module currently being compiled. Furthermore, all of the modules of the mutually-recursive group must be reachable by non-SOURCE imports from the module where the splice is to be run.
For example, when compiling module A, you can only run Template Haskell functions imported from B if B does not import A (directly or indirectly). The reason should be clear: to run B we must compile and run A, but we are currently type-checking A.
You are attempting to run the function (or more strictly value) x at compile time in the same module as x was defined, which is clearly stated to not be allowed.

Resources