Info on type family instances - haskell

Intro:
While checking out snoyman's "persistent" library I found myself wanting ghci's (or another tool) assistance in figuring out stuff.
ghci's :info doesn't seem to work as nicely with type-families and data-families as it does with "plain" types:
> :info Maybe
data Maybe a = Nothing | Just a -- Defined in Data.Maybe
...
> :info Persist.Key Potato -- "Key Potato" defined in example below
data family Persist.Key val -- Defined in Database.Persist
... (no info on the structure/identity of the actual instance)
One can always look for the instance in the source code, but sometimes it could be hard to find it and it may be hidden in template-haskell generated code etc.
Code example:
{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeFamilies, QuasiQuotes #-}
import qualified Database.Persist as Persist
import Database.Persist.Sqlite as PSqlite
PSqlite.persistSqlite [$persist|
Potato
name String
isTasty Bool
luckyNumber Int
UniqueId name
|]
What's going on in the code example above is that Template-Haskell is generating code for us here. All the extensions above except for QuasiQuotes are required because the generated code uses them.
I found out what Persist.Key Potato is by doing:
-- test.hs:
test = PSqlite.persistSqlite [$persist|
...
-- ghci:
> :l test.hs
> import Language.Haskell.TH
> import Data.List
> runQ test >>= putStrLn . unlines . filter (isInfixOf "Key Potato") . lines . pprint
where newtype Database.Persist.Key Potato = PotatoId Int64
type PotatoId = Database.Persist.Key Potato
Question:
Is there an easier way to get information on instances of type families and data families, using ghci or any other tool?

Does -ddump-splices show you the TH-generated code in this case?
Otherwise, :browse does give you info about data family instances, though not about type families.
You might want to file a ghc ticket - the :browse output looks mangled, and one might expect data family instances to be reported like class instances, by :info.

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.

Is there a way to generate a dhall schema from an haskell datatype?

I'm trying to rewrite a BIG yaml configuration file used in Haksell applicationusing dhall.
To do so I'm using json-to-dhall which requires a SCHEMA which is the type of the resuting expression. The problem is the actual schema is almost impossible to write manually as involves lots of sum types (and nested sum types). I tried to generate the schema by converting manually some parts of the yaml to dhall, and run dhall type. This give a schema that I can use with jston-to-dhall later. This works for simple types, but now I'm facing the problem with unions (of unions). Dhall needs type annotations to write the file I'm using to generate the type ... So I was wondering is there a way (either using a tool or modifying my haskell application) to either dump an Haskell data to a correct dhall file or at least generate the schema from the Haskell type.
Yes, you can generate the Dhall type from the Haskell type.
Here is an example of how to do so:
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE TypeApplications #-}
import Data.Either.Validation (Validation(..))
import Data.Text (Text)
import Dhall (FromDhall)
import GHC.Generics (Generic)
import Numeric.Natural (Natural)
import qualified Data.Text.IO as Text.IO
import qualified Dhall
import qualified Dhall.Core
data Mood = Happy | Sad
deriving (Generic, FromDhall)
data Person = Person { age :: Natural, name :: Text, mood :: Mood }
deriving (Generic, FromDhall)
main :: IO ()
main = do
case Dhall.expected (Dhall.auto #Person) of
Success result -> Text.IO.putStrLn (Dhall.Core.pretty result)
Failure errors -> print errors
... which outputs:
$ runghc ./example.hs
{ age : Natural, name : Text, mood : < Happy | Sad > }

Coercing types in Persistent

This is a "hello world" attempt that's currently failing - I am simply trying to run a selectList query on a SqLite database with the following code:
Database.Persist.Sqlite> runSqlite "database.sqlite" $ selectList [] [LimitTo 10]
<interactive>:46:1:
Couldn't match expected type ‘SqlBackend’
with actual type ‘PersistEntityBackend val0’
The type variable ‘val0’ is ambiguous
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
This almost seems too simple to screw-up... where did I go wrong?
As you probably already know, one of Haskell's strengths is strong typing. The persistent-sqlite package takes this to an extreme (which, in my opinion, is a good thing) by requiring that table entries have their own data type.
For instance, if you have a table which holds fruits that looks like this
_______________________
|Fruit ID | Fruit Name|
-----------------------
| 0 | "apple" |
| 1 | "orange" |
-----------------------
and you do a query against this table using persistent-sqlite, the results should be stored in a corresponding Fruit type
data Fruit = Fruit { fruitName::String }
Just creating said data type isn't enough, there is a bunch of boilerplate code to create the needed class instances to actually use this. Rather than create this all by hand, you can use the template Haskell magic in the persistent-template library to create all of this for you.
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Fruit
name String
deriving Show
|]
Your example code was actually correct, but was missing all of this stuff. Furthermore, the compiler didn't even know what type to try to use, so, the error message you got contained the following sentence
The type variable ‘val0’ is ambiguous
which was basically the compilers way of saying, "I don't know what type to extract the sql entry to." You can specify with an explicit type
print (fruits :: [Entity Fruit])
Finally, unfortunately, this code uses a bunch of GHC extensions. Putting this together, here is a more complete working simplest example.
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Control.Monad.IO.Class (liftIO)
import Database.Persist.Sqlite
import Database.Persist.TH
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Fruit
name String
deriving Show
|]
main :: IO ()
main = runSqlite "fruitDb.sqlite" $ do
fruits <- selectList [] [LimitTo 10]
liftIO $ print (fruits :: [Entity Fruit])
and just to be complete, here is how to populate the sqlite db to test this.
> sqlite3 fruitDb.sqlite
sqlite> create table fruit (id, name);
sqlite> insert into fruit values (0, "apple");
sqlite> insert into fruit values (1, "orange");
For posterity: I recently struggled with The type variable ‘backend0’ is ambiguous for a toy Sqlite example. The complier (rightly) couldn't figure out which backend I wanted to use for which BaseBackend backend = SqlBackend.
Turns out there are three of these: SqlBackend, SqlWriteBacknde and SqlReadBackend. Yes, for the first one, the resolved associated type happens to resolve to itself, if you wonder if it's a typo.
You can either fix by putting an explicit type signature somewhere (stick a type hole :: _ on an operation to get a hint), or by including the runMigration call in your operations, which magically fixes the type variable to SqlBackend.

Text.Printf with Data.Text?

I got sick of unpacking Data.Text instances all the time before printing them out for debugging and thought to just use Text.Printf for that. Unfortunately, I couldn't make it work:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Text
import Text.Printf
--instance PrintfArg Text where
-- toUPrintf = toUPrintf . unpack
main :: IO ()
main = do
let input :: Text = "abc"
printf "Input: %s\n" input
The error:
src/Main.hs:12:3:
No instance for (PrintfArg Text)
arising from a use of `printf'
Possible fix: add an instance declaration for (PrintfArg Text)
In a stmt of a 'do' block: printf "Input: %s" input
In the expression:
do { let input :: Text = "abc";
printf "Input: %s" input }
In an equation for `main':
main
= do { let input :: Text = ...;
printf "Input: %s" input }
After uncommenting the instance declaration:
src/Main.hs:7:7:
`toUPrintf' is not a (visible) method of class `PrintfArg'
src/Main.hs:7:19: Not in scope: `toUPrintf'
Any ideas?
EDITED
As suggested, tried TH, still no go:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
import Data.Text
import Language.Haskell.TH
import Text.Printf
runQ [d| instance PrintfArg Text where toUPrintf = toUPrintf . unpack|]
main :: IO ()
main = do
let input :: Text = "abc"
printf "Input: %s\n" input
Error:
src/Main.hs:9:40:
'toUPrintf' is not a (visible) method of class 'PrintfArg'
src/Main.hs:9:52: Not in scope: 'toUPrintf'
Help! It's amazing this doesn't work out of the box given all the advice to use Data.Text by default.
WARNING: text-format is unmaintained, no response from the author in 2 years. See other answers.
I'd look at the text-format package: it is similar to Text.Printf, but specifically designed for Data.Text.Lazy.
There are a few other advantages of text-format over Text.Printf:
The Buildable class is exposed, so it can be extended to support new parameter types.
It uses a simpler approach to varargs, which sidesteps problems one has in Text.Printf with accessing the return value.
It should be much faster, for several reasons:
it never converts to the inefficient String representation;
it doesn't build intermediate datatypes, unlike UPrintf in Text.Printf;
it uses the double-conversion package for rendering Double and Float, which is about 30 times faster than Prelude's methods.
Since this question was asked, the base and text libraries have been updated to support this. If you have base >= 4.7.0.0 and text >= 1.2.2.0, then the OP's MWE actually works:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Text
import Text.Printf
main :: IO ()
main = do
let input :: Text = "abc"
printf "Input: %s\n" input
Output:
$ ghci
GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help
Prelude> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, one module loaded.
*Main> main
Input: abc
*Main>
Leaving GHCi.
From the documentation:
The HPrintfType class provides the variable argument magic for hPrintf. Its implementation is intentionally not visible from this module.
While you could use TH to generate HPrintfType instances (because TH ignores export restrictions) the easiest solution is probably a printf' type function:
printt :: PrintType r => Text -> r
printt = printf . Data.Text.unpack
Another package worth checking out: formatting
Combinator-based type-safe formatting (like printf() or FORMAT) for Text.
Example:
format ("Person's name is " % text % ", age is " % hex) "Dave" 54

Compile-time assertions with GHC Haskell?

Coming from C++, I'm used to be able to build simple forms of compile-time assertions, where I could emit warnings or errors during compilation if some simple conditions (e.g. over simple algebraic expressions) weren't met via use of template meta-programming and/or cpp(1)
For instance, if I wanted to make sure my program compiles only when Int has at least a certain minBound/maxBound range or alternatively, if a loss-free (as in reversible) conversion from Int64 to Int is possible with the current compilation target. Is this possible with some GHC Haskell extension? My first guess would have been to use TH. Are there other GHC facilities that could be exploited to this end?
Here's a generalized and slightly simplified version of Anthony's example:
{-# LANGUAGE TemplateHaskell #-}
module StaticAssert (staticAssert) where
import Control.Monad (unless)
import Language.Haskell.TH (report)
staticAssert cond mesg = do
unless cond $ report True $ "Compile time assertion failed: " ++ mesg
return [] -- No need to make a dummy declaration
Usage:
{-# LANGUAGE TemplateHaskell #-}
import StaticAssert
$(staticAssert False "Not enough waffles")
Using TH for this isn't too bad. Here is a module that defines the desired assertion as part of a vestigial declaration:
{-# LANGUAGE TemplateHaskell #-}
module CompileTimeWarning where
import Control.Monad (unless)
import Data.Int (Int64)
import Language.Haskell.TH
assertInt = let test = fromIntegral (maxBound::Int) == (maxBound::Int64)
in do unless test $ report True "Int is not safe!"
n <- newName "assertion"
e <- fmap NormalB [|()|]
return $ [FunD n [Clause [] e []]]
Using the assertion involves a top-level declaration that isn't used for anything other than the assertion:
{-# LANGUAGE TemplateHaskell #-}
import CompileTimeWarning
$(assertInt)

Resources