Haskell DeriveGeneric pragma not being recognized - haskell

I have the following at the top of my Haskell file:
{-# LANGUAGE DeriveGeneric, OverloadedStrings, DefaultSignatures, TypeOperators, FlexibleContexts, RecordWildCards, FlexibleInstances, ExtendedDefaultRules #-}
module Main where
import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.Text (Text)
import Data.DateTime
import Data.Aeson
newtype Price = Price Float deriving Generic
However, when I run:
$ stack ghci
...
Prelude> :l myfile.hs
[1 of 1] Compiling Main ( myfile.hs, interpreted )
myfile.hs:13:38: error:
Not in scope: type constructor or class ‘Generic’
|
13 | newtype Price = Price Float deriving Generic
| ^^^^^^^
Failed, no modules loaded.
It seems to not accept my pragma for generics. What am I doing wrong? Looking at similar questions, this seems like it should work.

You also need to import GHC.Generics:
-- other imports
import GHC.Generics
-- more imports

Related

DuplicateRecordFields causes Template Haskell 'Illegal variable name' error

I do not understand why the DuplicateRecordFields language pragma is causing a compile time error in a template haskell splice.
Example:
-- TypeModule.hs
{-# LANGUAGE DuplicateRecordFields #-}
module TypeModule where
data A = A {foo :: Int} deriving Show
-- ThModule.hs
{-# LANGUAGE TemplateHaskell #-}
module ThModule where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import TypeModule
mkLambda :: Q [Dec]
mkLambda = [d| func :: A -> Int; func = foo |]
-- Lib.hs
module Lib where
import TypeModule
import ThModule
$mkLambda
{-
Illegal variable name: ‘$sel:foo:A’
When splicing a TH declaration: func_0 = (TypeModule.$sel:foo:A)
|
8 | $mkLambda
| ^^^^^^^^
-}
When I remove the DuplicateRecordFields pragma, the compile time error goes away.
I am using the DuplicateRecordFields pragma because I am parsing a number of different JSON objects which are responses from a REST API, and many of these JSON objects contain fields with identical names.
Right now I am looking for a way that does not use DuplicateRecordFields, but at the least I would like to understand what in particular is causing the compiler trouble.
This seems to be a known GHC issue: https://gitlab.haskell.org/ghc/ghc/-/issues/14848

Scotty and persistence - type error when using insert function

I've got the following application:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Main where
-- Scotty
import qualified Web.Scotty as S
import Network.Wai.Middleware.RequestLogger
import Network.Wai.Middleware.Static
import qualified Data.Text.Lazy as L
-- HTML rendering
import Text.Blaze.Html.Renderer.Text (renderHtml)
import qualified Text.Blaze.Html5 as H
import qualified Text.Blaze.Html5.Attributes as A
import Control.Monad.IO.Class
-- Database
import Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH
import Control.Monad.Trans.Resource (runResourceT, ResourceT)
import Control.Monad.Logger
-- URL generation
import System.Random
import Control.Monad (replicateM)
-- JSON
import Data.Map (fromList)
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Link
shortUrl L.Text
URLKey shortUrl
Primary shortUrl
longUrl L.Text
counter Int
deriving Show
|]
getURL :: L.Text -> IO (Maybe (Entity Link))
getURL shortId = runSqlite "links.db" $ do
maybeOriginal <- getBy $ URLKey shortId
pure maybeOriginal
-- I don't know what type to give this, that's probably the problem
addURL short long = runSqlite "links.db" $ do
insert $ Link short long
main :: IO ()
main = do
-- Connect to db and run migration
runSqlite "links.db" $ do runMigration migrateAll
S.scotty 3000 $ do
...
S.post "/shorten" $ do
-- Get URL
url <- S.param "url" :: S.ActionM L.Text
-- Generate a random short URL
randStr <- liftIO $ getRandStr 5
-- Add the urls to the database
liftIO $ addURL (L.pack randStr) url
-- Send JSON response with ID
S.json $ fromList [("id" :: String, randStr)]
I get the following error:
shortener> build (lib + exe)
Preprocessing library for shortener-0.1.0.0..
Building library for shortener-0.1.0.0..
Preprocessing executable 'shortener-exe' for shortener-0.1.0.0..
Building executable 'shortener-exe' for shortener-0.1.0.0..
[2 of 2] Compiling Main
/home/henry/haskell/shortener/app/Main.hs:86:5: error:
• Couldn't match type ‘PersistEntityBackend (Int -> Link)’
with ‘SqlBackend’
arising from a use of ‘insert’
• In the first argument of ‘($)’, namely ‘insert’
In a stmt of a 'do' block: insert $ Link short long
In the second argument of ‘($)’, namely
‘do insert $ Link short long’
|
86 | insert $ Link short long
| ^^^^^^
-- While building package shortener-0.1.0.0 (scroll up to its section to see the error) using:
/home/henry/.stack/setup-exe-cache/x86_64-linux-tinfo6/Cabal-simple_mPHDZzAJ_3.4.1.0_ghc-9.0.2 --builddir=.stack-work/dist/x86_64-linux-tinfo6/Cabal-3.4.1.0 build lib:shortener exe:shortener-exe --ghc-options " -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
I'm not sure how to resolve this type error and I haven't been able to find anything of use online. There was this answer with a similar problem, but the given type signature and several variations of it did not work.
It turns out I forgot a field when inserting. I had
insert $ Link short long
I needed
insert $ Link short long 0
for the counter field of Link.
Unfortunately the error didn't make that at all clear.

Haskell Noob: QuasiQuotes OverloadedStrings in Yesod not Working?

I'm not sure why I cant get this working....
I have QuasiQuotes and OverloadedStrings at the top of my hs file, at the top of main.hs, maindevel.hs and also declared in my foo.cabal file.
The ERROR:
Couldn't match type ‘[Char]’ with ‘Text’
Expected type: Text
Actual type: String
In the second argument of ‘($)’, namely
‘renderHtml (GHC.Base.id (toHtml y))’
In the expression:
putStrLn $ renderHtml (GHC.Base.id (toHtml y))
Code:
module Widgets.MainWidgets where
{-# LANGUAGE GADTs #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings, TypeSynonymInstances, FlexibleInstances #-}
import Import
import Text.Hamlet (shamlet)
import Text.Blaze.Html.Renderer.String (renderHtml)
import Data.Char (toLower)
import Data.List (sort)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import ClassyPrelude
import Yesod
import Data.Time.Clock
import Data.Time.Calendar
import Data.Time.LocalTime
import Data.Time.Format
getCurrYear :: String
getCurrYear = formatTime defaultTimeLocale "%y" getCurrentTime
getYear :: IO ()
getYear = putStrLn $ renderHtml
[shamlet|#{y}|]
where y = getCurrYear
I also have this in my foo.cabal file:
extensions: TemplateHaskell
QuasiQuotes
OverloadedStrings
NoImplicitPrelude
CPP
MultiParamTypeClasses
TypeFamilies
GADTs
GeneralizedNewtypeDeriving
FlexibleContexts
EmptyDataDecls
NoMonomorphismRestriction
DeriveDataTypeable
ViewPatterns
TupleSections
RecordWildCards
TypeSynonymInstances
FlexibleInstances
DeriveGeneric
Any idea why I get the String/Text conversion error?
Thanks in advance!
Adrian
The putStrLn from ClassyPrelude takes a Text, not a String. The simplest solution would be to change the Renderer import to the Text version of the module.

Yesod Persistent functions inaccessible from Handler. What should I include?

I'm having trouble with a slightly altered Yesod scaffold. I've got my Entity described like so in /config/models:
Artist
ident Int
value Text
and here is my handler at /Handler/Artist.hs
{-# LANGUAGE QuasiQuotes, TypeFamilies, GeneralizedNewtypeDeriving, TemplateHaskell,
OverloadedStrings, GADTs, FlexibleContexts #-}
module Handler.Artist where
import Import
import qualified Control.Monad.IO.Class as M
import Text.Hamlet (shamlet)
import Text.Blaze.Html.Renderer.String (renderHtml)
import Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH
import Control.Monad.IO.Class (liftIO)
getArtistR = concatMap (renderListElement . value) $ artists
where artists = selectList ([] :: [Filter Artist]) []
renderListElement name = renderHtml [shamlet|<li>#{name}|]
(I included with redundancy :) )
And lastly, my errors:
Rebuilding application... (using cabal)
Handler/Artist.hs:14:45: Not in scope: `value'
Build failure, pausing...
I'm not sure what I should do! Do I need to throw in something like $(widgetFile "artist") in the handler? Where is the patching going wrong? Any help would be so awesome. Thank you in advance!!!
You should prefix functions with model name, so value becomes artistValue.
Documentation contains example of generated code.

Processing standard quasiquote from external file in Haskell

I wanted to read an external Haskell source file for compile-time AST manipulation. How can I do that? I tried something like the following, but it didn't compile with the error message "TH.hs:15:12:
Declaration splices are not permitted inside declaration bracket".
--------
-- TH.hs
{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
module TH where
import Language.Haskell.TH
import Language.Haskell.TH.Quote
dd :: QuasiQuoter
dd = QuasiQuoter undefined undefined undefined ddDec
ddDec file_name = do
file_cts <- runIO (readFile file_name)
-- runQ [d| dummy = 0 |] -- This can compile.
runQ [d| file_cts |] -- This does not compile.
--------
-- main.hs
{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
import Language.Haskell.TH
import Language.Haskell.TH.Quote
import TH
[dd|input.hs|]
--------
-- input.hs
test = putStrLn "Hello."
--------
I also tried haskell-src-exts package, but this package seems to only parse and does not resolve identifiers and type checking. So I thought TH is a better choice.
import Language.Haskell.Exts.QQ
import Language.Haskell.TH.Quote
dd :: QuasiQuoter
dd = quoteFile dec

Resources