Using WinGHCi to implement first Haskell program - haskell

This is not my code :
import Data.Monoid (Endo (..), appEndo)
import Data.Foldable (foldMap)
-- | chainEndos chain a list of endomorphisms to create a new one
-- Point-free version is feasible and redable.
-- Level: Easy
--
-- Examples:
--
-- >>> chainEndos [(+1),(*3)] 2
-- 7
-- >>> chainEndos [('h':),('e':)] "llo"
-- "hello"
--
-- >>> chainEndos [] (12 :: Int)
-- 12
--
chainEndos :: [a->a] -> a -> a
chainEndos = appEndo . foldMap Endo
chainEndos' :: [a->a] -> a -> a
chainEndos' = foldr (.) id
main = print $ chainEndos [('h':),('e':)] "llo"
I would like to run this in the Haskell IDE : http://www.haskell.org/platform/
But WinGhci offers just a repl like structure ? How can I load this as haskell file and run it ?

Save it to file, then
File -> Load
that's all, after it you can call main

Related

How to generate imports and boilerplate lists using Template Haskell?

I'd like to replace this boilerplate with code generation:
import qualified Y15.D01
import qualified Y15.D02
import qualified Y15.D03
import qualified Y15.D04
import qualified Y15.D05
import qualified Y15.D06HM
import qualified Y15.D06IO
import qualified Y15.D06ST
import qualified Y15.D07
import qualified Y15.D08
import qualified Y15.D09
import qualified Y15.D10
import qualified Y15.D11
import qualified Y15.D12
import qualified Y15.D13
...
days :: [(String, [String -> IO String])]
days =
[ ("Y15.D01", i2ios [Y15.D01.solve1, Y15.D01.solve2])
, ("Y15.D02", i2ios [Y15.D02.solve1, Y15.D02.solve2])
, ("Y15.D03", i2ios [Y15.D03.solve1, Y15.D03.solve2])
, ("Y15.D04", i2ios [Y15.D04.solve1, Y15.D04.solve2])
, ("Y15.D05", i2ios [Y15.D05.solve1, Y15.D05.solve2])
, ("Y15.D06HM",i2ios [Y15.D06HM.solve1, Y15.D06HM.solve2]) -- Data.Map.Strict
, ("Y15.D06IO",ioi2ios [Y15.D06IO.solve1, Y15.D06IO.solve2]) -- Data.Array.IO
, ("Y15.D06ST",i2ios [Y15.D06ST.solve1, Y15.D06ST.solve2]) -- Data.Array.ST
, ("Y15.D07", i2ios [Y15.D07.solve1, Y15.D07.solve2])
, ("Y15.D08", i2ios [Y15.D08.solve1, Y15.D08.solve2])
, ("Y15.D09", i2ios [Y15.D09.solve1, Y15.D09.solve2])
, ("Y15.D10", i2ios [Y15.D10.solve1, Y15.D10.solve2])
, ("Y15.D11", s2ios [Y15.D11.solve1, Y15.D11.solve2])
, ("Y15.D12", i2ios [Y15.D12.solve1, Y15.D12.solve2])
, ("Y15.D13", i2ios [Y15.D13.solve1, Y15.D13.solve2])
]
where s2ios :: [a -> b] -> [a -> IO b]
s2ios = fmap (return .)
i2ios :: [a -> Int] -> [a -> IO String]
i2ios = fmap ((return . show) .)
ioi2ios :: [a -> IO Int] -> [a -> IO String]
ioi2ios = fmap (fmap show .)
https://github.com/oshyshko/adventofcode/blob/master/src/Main.hs
I am new to Template Haskell and I would appreciate any help/suggestions on where to start with these questions:
How to list modules in a project that match /Y\d\d.D\d\d.*/ pattern?
How to generate imports for p.1?
How to retrieve types of solve1 and solve2 fns from a given module?
How to generate days list?
With respect to question (2), Template Haskell cannot generate import statements. You can see a very old feature request for it in the bug tracker on GitLab but no one's been sufficiently inspired to implement it.
With respect to question (3), if modules have been imported and their names are available as strings, you can use TH to retrieve the type of a binding in each module like so. Given:
-- M001.hs
module M001 where
solve1 :: Int
solve1 = 10
-- M002.hs
module M002 where
solve1 :: IO Int
solve1 = return 20
-- THTest1.hs
{-# LANGUAGE TemplateHaskell #-}
module THTest1 where
import M001
import M002
import Language.Haskell.TH
let
modules = ["M001", "M002"]
showType :: String -> Q ()
showType nm = do
Just n <- lookupValueName nm
VarI _ typ _ <- reify n
reportWarning $ show nm ++ " has type " ++ show typ
return ()
in do mapM_ showType (map (++ ".solve1") modules)
return []
Then compiling THTest.hs will generate two warnings:
warning: "M001.solve1" has type ConT GHC.Types.Int
warning: "M002.solve1" has type AppT (ConT GHC.Types.IO)
(ConT GHC.Types.Int)
For question (4), here's a simplified example using modules M001 and M002 as defined above. Compile this program with ghc -ddump-splices to see the definition generated for days:
-- THTest2.hs
{-# LANGUAGE TemplateHaskell #-}
import M001
import M002
import Control.Monad
import GHC.Types
import Language.Haskell.TH
let
-- list of modules to search
modules = ["M001", "M002"]
-- assoc list of adapter function by argument type
funcs = [(ConT ''Int, 'return), (AppT (ConT ''IO) (ConT ''Int), 'id)]
getDay :: String -> Q Exp
getDay modname = do
-- look up name (e.g., M001.solve1)
Just n <- lookupValueName (modname ++ ".solve1")
-- get type of binding
VarI _ typ _ <- reify n
-- look up appropriate adapter function
let Just f = lookup typ funcs
-- ("M001", adapter_f M001.solve1)
[|($(pure $ LitE (StringL modname)),
$(pure $ AppE (VarE f) (VarE n)))|]
makeDays :: Q [Dec]
makeDays = do
[d| days :: [(String, IO Int)]
days = $(ListE <$> mapM getDay modules)
|]
in makeDays
main = do
forM days $ \(modname, action) -> do
putStr modname
putStr ": "
print =<< action
Then running it will output:
M001: 10
M002: 20

How can you print the type of a haskell expression in main? [duplicate]

I'm looking for a function that does what the GHCi :type command does.
Ideally, it would have a signature something like
getStaticType :: a -> String
a = getStaticType (1+2)
-- a = "(Num t) => t"
b = getStaticType zipWith
-- b = "(a -> b -> c) -> [a] -> [b] -> [c]"
(Note: this has nothing to do with Data.Dynamic. I just want the static type inferred from the compiler. In fact the function wouldn't need a runtime implementation at all, as all calls to it could be inlined as constants at compile time. I'm assuming it exists somewhere, since GHCi can do it)
You can do it like this:
import Data.Typeable
getStaticType :: Typeable a => a -> String
getStaticType = show . typeOf
Note that the type must be an instance of Typeable. You can derive Typeable automatically using the DeriveDataTypeable Haskell language extension and ... deriving (Typeable, ...).
Also note that polymorphic types cannot be identified in this way; you must always call a function with a specific type, so you can never get that polymorphic type information that you get in GHCi with compiled Haskell code.
The way GHCi does it is that it uses the GHC API to analyse an intermediary Haskell abstract syntax tree (AST) that contains type information. GHCi does not have the same restricted environment that your typical compiled Haskell program does; it can do lots of stuff to find out more information about its environment.
With TemplateHaskell, you can do it like this; first, create this module:
module TypeOf where
import Control.Monad
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
getStaticType :: Name -> Q Exp
getStaticType = lift <=< fmap pprint . reify
Then, in a different module (very important), you can do the following:
{-# LANGUAGE TemplateHaskell #-}
import TypeOf
main = putStrLn $(getStaticType 'zipWith)
This program outputs:
GHC.List.zipWith :: forall a_0 b_1 c_2 . (a_0 -> b_1 -> c_2) ->
[a_0] -> [b_1] -> [c_2]
You can use a better pretty-printer than the pprint function; take a look at the Language.Haskell.TH.Ppr module.
try http://www.haskell.org/haskellwiki/GHC/As_a_library
typed targetFile targetModule = do
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do
runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
let dflags' = xopt_set dflags Opt_ImplicitPrelude
setSessionDynFlags dflags'
target <- guessTarget targetFile Nothing
setTargets [target]
load LoadAllTargets
m <- getModSummary $ mkModuleName targetModule
p <- parseModule m
t <- typecheckModule p
return $ typecheckedSource d

How to use ByteStrings with QuickTest in DocTest?

How do I define the Arbitrary instance (as stated here) when using doctest and quickcheck?
Doctest and Cabal are set up as described here with a separate directory for tests.
The doctest line looks like this:
-- prop> (\s -> (decode . encode $ s == s)) :: ByteString -> Bool
decode :: ByteString -> ByteString
encode :: ByteString -> ByteString
Where and how do I define the Arbitrary instance, so that doctest can find it?
Note that I would want to define it in the test project.
Try
-- $setup
-- >>> import Control.Applicative
-- >>> import qualified Data.ByteString as ByteString
-- >>> import Test.QuickCheck
-- >>> instance Arbitrary ByteString where arbitrary = ByteString.pack <$> arbitrary
-- >>> instance CoArbitrary ByteString where coarbitrary = coarbitrary . ByteString.unpack
-- |
-- prop> \ s -> (decode . encode) s == s
decode:: ByteString -> ByteString
encode :: ByteString -> ByteString
Named chunks can be used for such definitions. However, each complete definition must be on one line, and doctest will report each use of >>> as a success or failure - so in this case, 6 attempts will be reported, even though only 1 of them is actually a test.

Haskell: getting the static type of an expression

I'm looking for a function that does what the GHCi :type command does.
Ideally, it would have a signature something like
getStaticType :: a -> String
a = getStaticType (1+2)
-- a = "(Num t) => t"
b = getStaticType zipWith
-- b = "(a -> b -> c) -> [a] -> [b] -> [c]"
(Note: this has nothing to do with Data.Dynamic. I just want the static type inferred from the compiler. In fact the function wouldn't need a runtime implementation at all, as all calls to it could be inlined as constants at compile time. I'm assuming it exists somewhere, since GHCi can do it)
You can do it like this:
import Data.Typeable
getStaticType :: Typeable a => a -> String
getStaticType = show . typeOf
Note that the type must be an instance of Typeable. You can derive Typeable automatically using the DeriveDataTypeable Haskell language extension and ... deriving (Typeable, ...).
Also note that polymorphic types cannot be identified in this way; you must always call a function with a specific type, so you can never get that polymorphic type information that you get in GHCi with compiled Haskell code.
The way GHCi does it is that it uses the GHC API to analyse an intermediary Haskell abstract syntax tree (AST) that contains type information. GHCi does not have the same restricted environment that your typical compiled Haskell program does; it can do lots of stuff to find out more information about its environment.
With TemplateHaskell, you can do it like this; first, create this module:
module TypeOf where
import Control.Monad
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
getStaticType :: Name -> Q Exp
getStaticType = lift <=< fmap pprint . reify
Then, in a different module (very important), you can do the following:
{-# LANGUAGE TemplateHaskell #-}
import TypeOf
main = putStrLn $(getStaticType 'zipWith)
This program outputs:
GHC.List.zipWith :: forall a_0 b_1 c_2 . (a_0 -> b_1 -> c_2) ->
[a_0] -> [b_1] -> [c_2]
You can use a better pretty-printer than the pprint function; take a look at the Language.Haskell.TH.Ppr module.
try http://www.haskell.org/haskellwiki/GHC/As_a_library
typed targetFile targetModule = do
defaultErrorHandler defaultFatalMessager defaultFlushOut $ do
runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
let dflags' = xopt_set dflags Opt_ImplicitPrelude
setSessionDynFlags dflags'
target <- guessTarget targetFile Nothing
setTargets [target]
load LoadAllTargets
m <- getModSummary $ mkModuleName targetModule
p <- parseModule m
t <- typecheckModule p
return $ typecheckedSource d

Proper way to import things already defined in the Prelude in Haskell

I'm trying to define a Foldable instance in Haskell and I have some problem with import.
So first try :
module MyList
where
import Data.Foldable
data MyList a = MyList [a]
instance Foldable (MyList) where
foldr f b (MyList as) = foldr f b as
Result (normal but annoying)
Ambiguous occurrence `foldr'
So, I guess I have to hide it from the Prelude :
module MyList
where
import Prelude hiding (foldr)
import Data.Foldable
data MyList a = MyList [a]
instance Foldable (MyList) where
foldr f b (MyList as) = foldr f b as
This compile, I load into ghci and try some basic stuff :
*MyList> foldr (:) "" (MyList "hello")
"hello"
*MyList> foldl (flip (:)) "" (MyList "hello")
<interactive>:1:0:
Ambiguous occurrence `foldl'
It could refer to either `Prelude.foldl', imported from Prelude at MyList.hs:4:0-28
or `Data.Foldable.foldl', imported from Data.Foldable at MyList.hs:5:0-19
*MyList>
So foldr works, but foldl doesn't. My first question is
Do I have to hide manually every single method defined in Data.Foldable from the Prelude is their a nice way to do it ?.
To avoid this problem , I tried to do an qualified import :
module MyList
where
import qualified Data.Foldable as F
data MyList a = MyList [a]
instance F.Foldable (MyList) where
foldr f b (MyList as) = foldr f b as
Seems to compile in ghc but
*MyList> foldr (:) "" (MyList "hello")
<interactive>:1:14:
Couldn't match expected type `[Char]'
against inferred type `MyList Char'
In the third argument of `foldr', namely `(MyList "hello")'
In the expression: foldr (:) "" (MyList "hello")
In the definition of `it': it = foldr (:) "" (MyList "hello")
foldr is not found but suprisingly F.foldr works in ghci.
*MyList> F.foldr (:) "" (MyList "hello")
"hello"
But in ghci only, if I'm trying to import MyList in file, foldr, F.foldr, MyList.F.foldr and MyList.foldr doesn't work.
Why does it work in ghci but not in real ?
I guess I have to import Data.Foldable again (and again in every files using MyList)
Is there a better way to do it (like exporting Data.Foldable in MyList) ?
(I'm a newbie in Haskell and especially with modules)
After having a couple of responses, it seems there is no clean solution to this problem. However, I'm pretty sure I'm not the first doing that, so
What is the common practice to deal with that kind of problem?
Thanks for you help.
Why does it work in ghci but not in real?
Because in your GHCi session you were typing expressions in the context of the MyList module, so F.foldr was in scope, but if you import MyList into another module then only the names exported by MyList, and the other modules you imported, are in scope.
Your guess is correct - in every module using Data.Foldable.foldr, you have to
import qualified Data.Foldable as F
The names exported by a module are unqualified; the qualification or not of those names is decided when the module is imported.
There have been proposals over the years to allow exporting qualified names, but to date nothing has been implemented.
Regarding the implicit Prelude import, you could add the following language pragma, and then explicitly import things from Prelude, but it might get uglier than simply hiding things from the Prelude or using an qualified import of Data.Foldable.
{-# LANGUAGE NoImplicitPrelude #-}
import Prelude (someFunction)
Why it might get uglier? Because you might have to import data types and functions that are taken for granted, or even functions that aren't explicitly used in the code:
{-# LANGUAGE NoImplicitPrelude #-}
module Main (main) where
-- we import fromInteger although it's not explicitly used
import Prelude (Int, foldl, fromInteger, (+), putStrLn, (.), ($), IO, show)
sum :: [Int] -> Int
sum = foldl (+) 0
main :: IO ()
main = putStrLn . show $ sum [1,2,3]
I told you about this not because it's a good solution, but just to know that there's such a thing.
Here's a variant of Thomas Eding solution, with less typing. Basically, you can import (in Prelude') Prelude hiding some functions, and then reexport Prelude; this will export Prelude minus those functions. This technique is generally useful to write a frontend module re-exporting only some functions in a library.
You can then reexport also Data.Foldable.
Where I replaced some Prelude functions with equivalents (examples for Foldable and Category).
module Prelude2 (module Prelude, module Data.Foldable, module Control.Category) where
import Prelude hiding (id, (.), foldr)
import Data.Foldable (Foldable, foldr) -- You might want to import everything.
import Control.Category (Category((.), id))
-- Try out replacing with:
-- import Control.Category ()
-- to see that no (.) is available.
Usage:
module Foo where
import Prelude()
import Prelude2
To wit, notice the types of foldr and (.) in Foo, as shown by GHCi:
$ ghci Foo.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 2] Compiling Prelude2 ( src-lib/Prelude2.hs, interpreted )
[2 of 2] Compiling Foo ( /Users/pgiarrusso/AeroFS/Repos/pts-bluevelvet/src-lib/Foo.hs, interpreted )
Ok, modules loaded: Foo, Prelude2.
*Foo> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
*Foo> :t (.)
(.) :: Category cat => cat b c -> cat a b -> cat a c
*Foo>
If you try the suggestion of replacing
import Control.Category ()
GHCi will show you that (.) is not defined at all in Foo:
*Foo> :r
[1 of 2] Compiling Prelude2 ( src-lib/Prelude2.hs, interpreted )
[2 of 2] Compiling Foo ( /Users/pgiarrusso/AeroFS/Repos/pts-bluevelvet/src-lib/Foo.hs, interpreted ) [Prelude2 changed]
Ok, modules loaded: Foo, Prelude2.
*Foo> :t (.)
<interactive>:1:1: Not in scope: `.'
You could make a Prelude' module that exports only the stuff you want. Then you could begin your actual module as follows:
import Prelude ()
import Prelude'
import Data.Foldable
Granted you have to do the grunt work in Prelude', but at least it is reusable.
Clarification:
Prelude'.hs:
module Prelude' (
id
, Num (..)
, everthing you want exported for your 'customized' prelude module goes in this list
) where
I've re-read your question and some of your comments and I guess the closest you can get to what you want is something like this:
module MyList
(
module Data.Foldable,
MyList(..)
)
where
import Data.Foldable
import Prelude (($))
data MyList a = MyList [a]
instance Foldable (MyList) where
foldr f b (MyList as) = foldr f b as
Basically, MyList re-exports the Data.Foldable module, so that someone using your module won't have to import Data.Foldable again, but... she will have to hide some functions from the Prelude.
module Main (main) where
import Prelude hiding (foldr)
import MyList
mySum :: MyList Int -> Int
mySum = foldr (+) 0
main :: IO ()
main = putStrLn . show . mySum $ MyList [1,2,3]
IMHO, this is a good thing. You should not decide how and what someone imports in his own modules.

Resources