I've made a calculator in haskell which I run from within GHCi. However since the final number can be an integer or double I've made the type declaration
calc :: String -> Either Integer Double
However the output of the function always has either left or right in front of it for example
Left 7
Right 8.4
Is there a way I can stop the left and right being printed?
When you evaluate this function, GHCi automatically calls putStrLn . show on the result. It is the show function for Either Integer Double which is adding the Left and Right strings.
To avoid this, you can use either show show instead, which will apply the show function only to the numbers stored inside the Either, so
> putStrLn . either show show $ calc ...
should give you what you want.
The fancy way
(Probably, the other, less fancy solution below is better for you)
If you're only concerned about ghci, there's now (GHC>=7.6) the possibility to use a custom print function. You'd just specify, say,
type CalcResult = Either Integer Double
calcPrint :: CalcResult -> IO()
calcPrint (Left intg) = print intg
calcPrint (Right floatng) = print floatng
and then load ghci by
$ ghci YourModule.hs -interactive-print=YourModule.calcPrint SpecPrinter
This way, it's going to be a bit annoying: calcPrint can only use CalcResult, so you wouldn't be able to display anything else. To get around this, you can use a type class,
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverlappingInstances #-}
data CalcResult -- We must prevent the 'Show' instance of 'Either' from
= IntegerResult Integer -- getting in our way. (This type is better anyway,
| FloatingResult Double -- you might want to add more types (e.g. 'Complex')
-- later, which is no good with 'Either'.)
class CalcShow c where
calcShow :: c -> String
instance (Show c) => CalcShow c where
calcShow = show
instance CalcShow CalcResult where
calcShow (IntegerResult intg) = show intg
calcShow (FloatingResult floatng) = show floatng
calcPrint :: CalcShow c => c -> IO()
calcPrint = putStrLn . calcShow
This way you will be able to display calculation results the way you'd like, as well as anything in the old Show class:
$ ghci-7.6 GHCI_Customprint.hs -interactive-print=GHCI_Customprint.calcPrint
GHCi, version 7.6.2: 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 1] Compiling GHCI_Customprint ( GHCI_Customprint.hs, interpreted )
Ok, modules loaded: GHCI_Customprint.
*GHCI_Customprint> "blubb"
"blubb"
*GHCI_Customprint> [1..5]
[1,2,3,4,5]
*GHCI_Customprint> IntegerResult 39
39
*GHCI_Customprint> FloatingResult $ -236.24983e+89
-2.3624983e91
The other solution
As I said, you should be using a custom data type as your result, not Either. Why, if you have such a type you might as well give it a Show instance that does what you want:
instance Show CalcResult where
show (IntegerResult intg) = show intg
show (FloatingResult floatng) = show floatng
For your purposes, this will probably be just fine, you can use it in ghci without any extra tweaks and it does what you want. Only, there's a kind of law that a Show instance should produce valid Haskell code. But that's actually ok, because you can make 3 or 27.8 valid "constructors" for CalcResult!
instance Num CalcResult where
fromInteger = IntegerResult
IntegerResult a + IntegerResult b = IntegerResult $ a+b
...
instance Floating CalcResult where
fromRational = FloatingResult . fromRational
...
Related
:type is not enough because the expression I want might include locally defined variables like things assigned with <-, let or where. Typed holes (replacing the expression with _ and loading with ghc) are close, but they give you what's accepted there, which might be more general than the expression you're curious about.
I thought I found the jackpot with :type-at, but I can't get it to work like I'd hope. With this file, named "thing.hs":
something :: ()
something = ()
main :: IO ()
main = return something
This is the result I get when using :type-at:
> :set +c
> :l thing.hs
[1 of 1] Compiling Main ( thing.hs, interpreted )
Ok, one module loaded.
Collecting type info for 1 module(s) ...
> :type-at thing.hs 5 8 5 13 -- "return" on last line
<no location info>: error: not an expression: ‘’
> :type-at thing.hs 5 1 5 4 -- "main" on last line
:: IO ()
> :type-at thing.hs 5 15 5 23 -- "something" on last line
<no location info>: error: not an expression: ‘’
That's basically the same as using :type. I was hoping I'd even be able to pass it the span for return something and get Monad a => a () or IO (). Would be even cooler if one could select between seeing the type of the expression alone and the type of the expression "at that point" (after being restricted by the type that would appear with a type hole), but either would be fine.
When I try :type-at thing.hs 5 8 5 14, I get :: () -> IO (). :type-at thing.hs 5 14 5 24 also works, as does :type-at thing.hs 5 14 6 1.
So, the right bound should be the cell one past the end of the expression.
Sometimes one can simply use a typed hole in front of the expression you are curious about works, using the hole as if it were a function. For instance
return (f 3)
---->
return (_ (f 3))
In this way, the hole will be typed with something like WantedType -> OtherType, where WantedType is the type of f 3.
This is not ideal, though, since the hole will prevent type inference to do its job. I.e., sometimes the type of f 3 is polymorphic, and its context forces it to be instantiated. For instance, 4 + length [] makes 4 to be Int, even if it can be of any Num type. Using (_ 4) + length [] introduces a function between the arbitrary Num type (which will get defaulted to Integer) and the needed Int, making type inference misbehave.
Instead, an alternative could be to use the translation
return (f 3)
------>
return (f 3 `asTypeOf` _)
This should play better with the type inference, and return the right™ type.
Of course, figuring out how :type-at works should be better. Still, the type hole trick is not too inconvenient when you have an editor already open at the spot.
I believe #chi answer can be improved (by avoiding the type inference issue ) by using a Dummy unary type constructor which does not implement the Show typeclass and using it with the print function :
someExpressionWeSearchType = Right $ Just (1 , ["Foo"] , getLine)
data Dummy a = Dummy a
main = do
putStrLn "Here we go"
--some code here...
let exp = someExpressionWeSearchType
--Debug stuff =>
print $ Dummy exp
-- other code here
putStrLn "Done"
This gives the following result when loaded :
Prelude> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
test.hs:11:3: error:
* No instance for (Show
(Dummy (Either a0 (Maybe (Bool, [[Char]], IO String)))))
arising from a use of `print'
* In a stmt of a 'do' block: print $ Dummy exp
In the expression:
do putStrLn "Here we go"
let exp = someExpressionWeSearchType
print $ Dummy exp
putStrLn "Done"
In an equation for `main':
main
= do putStrLn "Here we go"
let exp = ...
print $ Dummy exp
....
|
11 | print $ Dummy exp
| ^^^^^^^^^^^^^^^^^
Failed, no modules loaded.
So we can see that type inside the Dummy : Either a0 (Maybe (Bool, [[Char]], IO String))
I need to communicate some information from compile scripts into Template Haskell. Currently the compile scripts keep the information in the system environment, so I just read it using System.Environment.getEnvironment wrapped in runIO. Is there a better way, such as passing some arguments to ghc (similar to -D... for the C pre-processor), or perhaps something specifically designed for this purpose in TH?
Since so many people are interested in the question, I'll add my current approach, perhaps somebody will find it useful. Probably the best way would be if TH allowed to read -D parameters on GHC's command line, but it seems nothing like this is currently implemented.
A simple module allows TH to read compile-time environment. A helper function also allows to read files; for example read the path of a configuration file from the environment and then read the file.
{-# LANGUAGE TemplateHaskell #-}
module THEnv
(
-- * Compile-time configuration
lookupCompileEnv
, lookupCompileEnvExp
, getCompileEnv
, getCompileEnvExp
, fileAsString
) where
import Control.Monad
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Language.Haskell.TH
import Language.Haskell.TH.Syntax (Lift(..))
import System.Environment (getEnvironment)
-- Functions that work with compile-time configuration
-- | Looks up a compile-time environment variable.
lookupCompileEnv :: String -> Q (Maybe String)
lookupCompileEnv key = lookup key `liftM` runIO getEnvironment
-- | Looks up a compile-time environment variable. The result is a TH
-- expression of type #Maybe String#.
lookupCompileEnvExp :: String -> Q Exp
lookupCompileEnvExp = (`sigE` [t| Maybe String |]) . lift <=< lookupCompileEnv
-- We need to explicly type the result so that things like `print Nothing`
-- work.
-- | Looks up an compile-time environment variable and fail, if it's not
-- present.
getCompileEnv :: String -> Q String
getCompileEnv key =
lookupCompileEnv key >>=
maybe (fail $ "Environment variable " ++ key ++ " not defined") return
-- | Looks up an compile-time environment variable and fail, if it's not
-- present. The result is a TH expression of type #String#.
getCompileEnvExp :: String -> Q Exp
getCompileEnvExp = lift <=< getCompileEnv
-- | Loads the content of a file as a string constant expression.
-- The given path is relative to the source directory.
fileAsString :: FilePath -> Q Exp
fileAsString = do
-- addDependentFile path -- works only with template-haskell >= 2.7
stringE . T.unpack . T.strip <=< runIO . T.readFile
It can be used like this:
{-# LANGUAGE TemplateHaskell #-}
import THEnv
main = print $( lookupCompileEnvExp "DEBUG" )
Then:
runhaskell Main.hs prints Nothing;
DEBUG="yes" runhaskell Main.hs prints Just "yes".
It looks like what you are trying to do here, The -D option in ghc seems to define a compile time variable.
Here, on the same subject is a question that seems to also answer the other part of your question.
From what I can tell, to do conditional compilation, you do something like:
#ifdef MACRO_NAME
//Do stuff here
#endif
I'm currently in the process of solving euler problems to improve in Haskell. Though, my attempt at solving problem n° 43 produces no output.
Just to be clear, I'm not asking for help on the "problem algorithmic" part, even if I'm wrong. I'm specifically asking for help on the Haskell part.
So, I divided my attempt into simple functions. First I build a list holding all 0-9pandigital numbers, then I define functions to cut those numbers into the interesting part and finally I filter only the correct ones:
import Data.List
main = print $ foldl1 (+) goodOnes
pands = [read x :: Integer | x <- permutations "0123456789", head x /= '0']
cut3from :: Integer -> Integer -> Integer
cut3from x n = mod (div x nd) 1000
where
l = fromIntegral $ length $ show x :: Integer
nd = 10 ^ (l - 3 - n)
cut :: Integer -> [Integer]
cut x = map (cut3from x) [1..7]
testDiv :: Integral a => [a] -> Bool
testDiv l = and zipped
where
zipped = zipWith mult l [2, 3, 5, 7, 11, 13, 17]
mult :: Integral a => a -> a -> Bool
mult a b = mod a b == 0
goodOnes = filter (testDiv.cut) pands
Though, when compiling it (with -O2) and executing it, it outputs nothing. Even with +RTS -s.
I'd like advice on two points mainly:
why is this code wrong, how to improve it
how could I have debugged it myself
as a side point, if you have advice on how to handle Integer and Ints easily, please post them. I find it troublesome to use both together.
But any other remark is welcome!
EDIT: it seems that GHCi slowly builds the result list goodOnes and is able to answer after a long time (only in GHCi, when compiled it's still as reported). That's certainly not a behaviour I can wish to observ in my programs. How could I fix that ?
EDIT2: it now works when compiled too (code unchanged). I'm puzzled about all those inconsistencies and would welcome any explanation!
EDIT3: semihappy ending: after a reboot, all went back to normal ~~
To answer "how could I have debugged it myself":
Check out ghci.
prompt$ ghci
GHCi, version 6.12.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.
Loading package ffi-1.0 ... linking ... done.
Prelude>
It's an interactive interpreter that allows you to:
load files and play with the contents
Prelude> :load myfile.hs
[1 of 1] Compiling Main ( myfile.hs, interpreted )
Ok, modules loaded: Main.
*Main> xyz "abc"
*Main> 3
type in definitions and use them
*Main> let f x = x + 3
evaluate expressions and see the results
*Main> f 14
17
inspect types and kinds
*Main> :t f
f :: (Num a) => a -> a
*Main> :k Maybe
Maybe :: * -> *
Make sure you test each of the little pieces before you test the whole shebang -- it's easier to find problems in small things than in big ones. Check out QuickCheck if you're into unit tests.
For the Ints vs. Integers issue, you could sidestep the issue by only using Integers (of course, they may be less efficient: YMMV). Data.List has functions prefixed with generic, i.e. genericLength which are quite useful.
Here's how I compiled and ran it:
prompt$ ghc euler43.hs
prompt$ ./a.out
<some number is printed out>
Simple question. Is it possible to check the type of a variable that is only alive within a function?
For example:
main = do
x <- something
How can I check the type of x?
I can't do :type x in ghci because x is not global.
Another way (quite similar to RobAgar's and hacky as well) is to explicitly specify some wrong type for the local variable in question, e.g.:
main = do
x <- getArgs
x :: () -- let's cast it to unit! ;)
print $ head x
Then ghci will give us an error:
Couldn't match expected type `()' with actual type `[String]'
which shows that the actual type of "x" is [String].
There is a hacky way:
main = do
x <- something
foo x
where foo is any old function which doesn't take an argument of the type you think x might be. You'll get a nice error from GHC which includes the type expected by foo and the type actually passed in.
You can use the GHCi Debugger:
> ghci a.hs
GHCi, version 7.0.4: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
[1 of 1] Compiling Main ( a.hs, interpreted )
Ok, modules loaded: Main.
*Main> :break 4
Breakpoint 0 activated at a.hs:4:8-14
*Main> :main
Stopped at a.hs:4:8-14
_result :: IO String = _
[a.hs:4:8-14] *Main> :list
3 main = do
4 x <- getLine
^^^^^^^
5 return x
[a.hs:4:8-14] *Main> :step
asd
Stopped at a.hs:5:3-10
_result :: IO String = _
x :: String = _
[a.hs:5:3-10] *Main> :t x
x :: String
There is no easy way to do this. If your something function is in the global scope, you can check the type of that function. If it really is in your main function, its type is going to be IO SomeType, where SomeType is probably what you're looking for.
Another option is Scion which is basically an external wrapper over the GHC api which acts as a server providing IDE-like capabilities for editors like Emacs and Vim.
In the readme, it mentions the "experimental" command C-c C-t which shows the type of the identifier at point, including local identifiers. However, this will only work if your file type-checks.
This lets you find out the type of a local declaration without compiling your file or loading into GHCi, which means it won't disrupt your flow of thought as much.
This is sort of the obvious non-answer. Given a local binding of the form
x <- something
In order to know the type of x, you merely need to know the type of something. Given something has the type m a (for some Monad m), x must therefore have the type a.
I'm trying to run the BinaryDerive.hs script as per the instructions in the Data.Binary doc, which states:
To derive the instance for a type,
load this script into GHCi, and bring
your type into scope. Your type can
then have its Binary instances derived
as follows:
$ ghci -fglasgow-exts BinaryDerive.hs
*BinaryDerive> :l Example.hs
*Main> deriveM (undefined :: Drinks)
However when I try to follow those instructions I get:
c:\Scripts\Haskell>$ ghci -fglasgow-exts BinaryDerive.hs
*BinaryDerive> :l TemperatureRecord.hs
[1 of 1] Compiling TemperatureRecord (TemperatureRecord.hs, interpreted )
Ok, modules loaded:TemperatureRecord.
*TemperatureRecord> deriveM (undefined :: TemperatureRecord)
(interactive):1:0: Not in scope: 'deriveM'
I am assuming that there is an additional step that was not specified that a beginner, like myself would not be aware of. It seems the root of the problem is that loading the TemperatureRecord takes BinaryDerive out of scope. Anyone have any ideas?
My understanding of ghci's loading/namespacing mechanisms is full of holes, but since nobody else has answered, here are some guessses:
Try :m + BinaryDerive after :l Example.hs
Add import BinaryDerive at the top of Example.hs
Don't add module TemperatureRecord where at the top of Example.hs
try
$ ghci -fglasgow-exts
Prelude> :l BinaryDerive TemperatureRecord
the .hs's are not necessary
Then you can access TemperatureRecord in a similar manner to this example (JSON Doc type taken from Real World Haskell, with some added Data and Typeable derives)
$ ghci -fglasgow-exts -XDeriveDataTypeable
Prelude> :l Binaryderive JSON
[1 of 2] Compiling JSON ( JSON.hs, interpreted )
[2 of 2] Compiling BinaryDerive ( Binaryderive.hs, interpreted )
Ok, modules loaded: BinaryDerive, JSON.
*BinaryDerive> deriveM (undefined::JSON.Doc)
instance Binary JSON.Doc where
put Empty = putWord8 0
put (Char a) = putWord8 1 >> put a
put (Text a) = putWord8 2 >> put a
put Line = putWord8 3
put (Concat a b) = putWord8 4 >> put a >> put b
put (Union a b) = putWord8 5 >> put a >> put b
get = do
tag_ <- getWord8
case tag_ of
0 -> return Empty
1 -> get >>= \a -> return (Char a)
2 -> get >>= \a -> return (Text a)
3 -> return Line
4 -> get >>= \a -> get >>= \b -> return (Concat a b)
5 -> get >>= \a -> get >>= \b -> return (Union a b)
_ -> fail "no parse"
Thanks everyone for the answers. I tried both of them and neither worked, however, the answers I saw did lead me too a solution.
$ ghci -fglasgow-exts -XDeriveDataTypeable
Prelude> :l Binaryderive TemperatureRecord
Prelude> :m Binaryderive TemperatureRecord
Prelude BinaryDerive TemperatureRecord>deriveM (undefined :: TemperatureRecord)
The above worked for me. However, I am not using that solution in practice. I am working on getting a more automatic solution to work. Anyway thanks for helping me get something that works.