Haskell Format String Output "(x, y)," - haskell

So I am trying to output a list of Points "(X,Y) \n" but I cant get it working.
Both values X and Y are Floats. I tried the module text-format but I cant make it work with Char and Float and the same time.
Anyone has an idea on how to make this work?
BEst regards
UPDATED:
format_pts_string cs = [
format ("(" % a % ", " % b % ")")
| c <- cs]
This code is NOT working, Error -> Print Of Error

From the code of your question, I guess you want to convert a list of Double pair to a list of String, as said in comment, you may not need use Data.Text.Format package, since the basic function show can convert it to String properly as:
format_pts_string::[(Double, Double)]->[String]
format_pts_string cs = map (\c-> (show c) ++ "\n") cs
or use list comprehension:
format_pts_string::[(Double, Double)]->[String]
format_pts_string cs = [show c ++ "\n" | c <- cs]
Furthermore, if need to control output format, you can use ++ to concatenate the String, here is an example:
format_pts_string::[(Double, Double)]->[String]
format_pts_string cs = map formatPair cs
where formatPair (a, b) = "(" ++ (show a) ++ ", " ++ (show b) ++ ")" ++ "\n"
if you still love to use module text-format, you may need to enable OverloadedStrings language extension to convert String to Format type for call format function as:
{-# Language OverloadedStrings #-}
import Data.Text.Lazy (unpack)
import Data.Text.Format (format)
format_pts_string::[(Double, Double)]->[String]
format_pts_string cs = [unpack $ format "({}, {})\n" (c::(Double, Double))| c <- cs]
or don't use OverloadedStrings language extension, use formString in Data.String instead, but it is verbose as:
...
import Data.String (fromString)
...
[unpack $ format (fromString "({}, {})\n") (c::(Double, Double))| c <- cs]

Is this what you have in mind?
main = let ps = [
(1.0,1.0),
(2.0,2.0),
(3.0,3.0),
(4.0,4.0),
(5.0,5.0),
(6.0,6.0)
]
in mapM print ps
output :
(1.0,1.0)
(2.0,2.0)
(3.0,3.0)
(4.0,4.0)
(5.0,5.0)
(6.0,6.0)

Related

Lookup values inside a Cassava-ingested CSV

I successfully read in a CSV using Cassava (http://hackage.haskell.org/package/cassava) with this:
getData = do
csvData <- BL.readFile "data.csv"
case decodeByName csvData of
Left err -> putStrLn err
Right (_, v) -> V.forM_ v $ \ p ->
putStrLn $ col1 p ++ "," ++ col2 p ++ "," ++ (show $ col3 p) ++ "," ++ (show $ col4 p) ++ "," ++ (show $ col5 p) ++ "," ++ col6 p ++ "," ++ (show $ col7 p) ++ "," ++ (show $ col8 p) ++ "," ++ (show $ col9 p) ++ "," ++ (show $ col10 p)
What I actually need to do is use the values in col3 as keys to find values in col10.
Someone suggested that I use Map from Data.Map (https://hackage.haskell.org/package/containers-0.4.0.0/docs/Data-Map.html) for this, but I'm not sure how to approach this.
Everything I have tried so far has not worked. I assume you enter the Map inside the Right case, along the lines of:
Right (_, v) -> Map (V.forM_ v) ???
But I am stuck on how to proceed. Would appreciate any suggestions. Ideally, I would want to modify getData so that it is getData keyToFetch = ... -- and that keyToFetch would be used in the Map.
Yes, it is probably a good idea to use Data.Map to find values in col10 using values in col3 as keys.
As we have little data about col3, col10 and the exact data type you are using, I will resort to adapting the decodebyName example in the Cassava documentation to the idea of generating a map object. The example is based on a very simple {name, salary} type of record.
The two branches of the case of construct have to return a common type, in our case a Data.Map object instead of an IO () action. Fortunately, the error function is flexible enough that it can pretend to be of the appropriate type.
This would give this sort of code:
{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative
import qualified Data.ByteString.Lazy as BL
import Data.Csv
import qualified Data.Vector as V
import qualified Data.Map as M
import Control.Monad (forM_)
data Person = Person
{ name :: !String
, salary :: !Int
} deriving (Show, Ord, Eq) -- need that for Map objects
instance FromNamedRecord Person where
parseNamedRecord r = Person <$> r .: "name" <*> r .: "salary"
-- build a map object:
makeMap :: V.Vector Name -> V.Vector Person -> M.Map String Int
makeMap hdr pvec =
-- with name and salary playing the role of col3 and col10:
let pls = V.toList pvec -- get a list
zls = zip (map name pls) (map salary pls)
in M.fromList zls
showRecord :: String -> Int -> String
showRecord name salary = name ++ " earns " ++ (show salary) ++ " dollars"
main :: IO ()
main = do
csvData <- BL.readFile "salaries.csv"
let ma = case decodeByName csvData of
Left errMsg -> error $ "decodeByName failed: " ++ errMsg
Right (hdr, pvec) -> makeMap hdr pvec
-- print out the Map object:
putStrLn $ "Contents of map object:"
putStrLn $ show ma
putStrLn $ ""
forM_ (M.toList ma) (\(n,s) -> putStrLn $ showRecord n s)
let sal1 = M.lookup "John Doe" ma
putStrLn $ "sal1 = " ++ (show sal1)
--
Execution:
Contents of map object:
fromList [("Jane Doe",60000),("John Doe",50000)]
Jane Doe earns 60000 dollars
John Doe earns 50000 dollars
sal1 = Just 50000
Note that I have to use plain lists extensively, as for some reason there is no direct route from vectors to maps, something discussed already in this SO question.

When tracing in Haskell, how does one `show` a value whose data type is not known at compile-time?

I am using GHC version 8.0.2 on Windows 7, & module Debug.Trace.
In the trace of the parse function below, my insertion of ++ show first results in the following error:
No instance for (Show a) arising from a use of `show'
Possible fix:
add (Show a) to the context of
the type signature for:
parse :: Parser a -> String -> [(a, String)]
In the first argument of (++)', namelyshow first'
In the second argument of (++)', namely
show first ++ "," ++ show second ++ ")]"'
In the second argument of (++)', namely
" -> [(" ++ show first ++ "," ++ show second ++ ")]"'
My question: is there a way to show the first element of the ordered pair (a,String) even though its type is not known at compile-time?
My source code is shown below:
{-# LANGUAGE MonomorphismRestriction #-}
import Data.Typeable
import Data.Char
import Debug.Trace
newtype Parser a = P ( String -> [(a,String)] )
parse :: Parser a -> String -> [(a,String)]
parse (P p) input | trace
( let result = (p input)
element = head result
first = fst element
second = snd element
in ("parse maps " ++ input ++ " -> [(" ++ show first ++ "," ++ show second ++ ")]")
) False = undefined
parse (P p) input = p input
nextChar :: Parser Char
nextChar = P ( \input -> case input of { [] -> [] ; (c:cs) -> [(c,cs)] } )
I am hoping to trace evaluation of parse nextChar "ABCD".
Yes, sure, just follow the instructions in the error:
parse :: Show a => Parser a -> String -> [(a,String)]
Once you're done debugging, you can delete the call to trace and the Show constraint; then you'll be able to parse un-Showable things again.

Accessing a list entry and showing its values

I have a function
(.#.) :: [a] -> Integer -> a -- 1-indexing with 'Integer'
xs .#. j = xs !! (fromIntegral $ j-1)
showIntegers :: [Integer] -> String
showIntegers r = let
str = concat $ "List: " : [r (.#.) j | j <- [1..length r]]
How can I show r (.#.) j as a Char/String rather than an integer? I tried using show, but it gave me an error.
Here is an example of how I used show:
str = concat $ "List: " : [show $ r (.#.) j | j <- [1..length r]]
Example input and output:
> showIntegers [1,2,3]
List: 1 2 3
You should just use Data.List.intercalate or even better use unwords.
import Data.List
showIntegers :: [Integer] -> String
showIntegers r = "List: " ++ intercalate " " $ map show r
--showIntegers r = "List: " ++ unwords $ map show r
EDIT: In either case you should avoid using !! especially to enumerate the original list.
First I would get rid of .#. it is just going to confuse you to use a different numbering system, best to rip that bandaid off.
Next realize that [show $ r !! j <- 0 .. length r - 1] is the same as map show r (and the latter is standard).
Now going with that you have: concat $ "List: " : (map show r) which creates List: 123 because we lost the spaces.
We could reproduce the spaces but what is the difference between using intercalate and concat? Honestly the best solution without using intercalate would be to reproduce intercalate (whose source code is available on Hackage).
Just remove the parenthesis around (.#.) and it works.
If you have an infix operator !#$ , with something before and after it, e.g. x !#$ y, you must not use parentheses. In the other cases, add parentheses, like in the type declaration.
(this technically answers the question, but Guvante's advice is better.)

Parsing .csv into clauses in Haskell

I am trying to convert a .csv of
femin,femin,1,f,woman,women,
aqu,aqu,1,f,water,waters,
..
into a file of .pl like
noun(femin,femin,1,f,trans(woman,women)).
noun(aqu,aqu,1,f,trans(water,waters)).
..
here is my current source code:
-- get from "femin, femin, 1, f, woman, women" to noun(femin, femin, 1, f ,trans(woman,women)).
import qualified Data.Attoparsec as P
data NounClause = NounClause
{
nom :: String,
gen :: String,
declension :: String,
gender :: String,
sgtrans :: String,
pltrans :: String
} deriving Show
parseNounClause :: P.Parser NounClause
parseNounClause = do
nom <- String
char ","
gen <- String
char ","
declension <- String
char ","
gender <- String
char ","
sgtrans <- String
char ","
pltrans <- String
return $ NounClause nom gen declension gender sgtrans pltrans
However, this does not seem to be working. Why is this so?
Also, how can I apply this parser to each line? Here also is my function that takes the parsed data and returns a string.
c = ","
convert :: NounClause -> String
convert NounClause = "noun(" ++ nom ++ c ++ gen ++ c ++ declension ++ c ++ gender ++ "trans(" ++ sgtrans ++ c ++ pltrans ++ "))."
I very much thank anyone who helps me on this project; their contribution is most valuable to me.
If you use the String parser, it tries to consume as much input as possible. This includes the commas in your file.
So you construct a parser that reads everything except for commas.
import qualified Data.Attoparsec.Text as P
import Data.Text(unpack)
entry = fmap unpack (P.takeWhile (/=','))
unpack is used to convert the parsed info of type Text into a String.
Then you need an additional parser that reads a comma.
separator = P.char ','
Then we combine this to parse a NounClause
parseNounClause :: P.Parser NounClause
parseNounClause = do
nom <- entry
separator -- don't need the comma so no need to keep it.
gen <- entry
separator
declension <- entry
separator
gender <- entry
separator
sgtrans <- entry
separator
pltrans <- entry
separator
return $ NounClause nom gen declension gender sgtrans pltrans
So now you want to read multiple lines. This is the same as the comma but now with a newline symbol.
We parse an entry and a newline symbol alternating. To compensate for n lines but only n-1 newline symbols we make a distinction for the first line. The many' combinator allows us to parse zero or more lines of the same format.
multiLines = do x <- parseNounClause
xs <- many' (do P.endOfLine
clause <- parseNounClause
return clause
)
return (x:xs)
So now wee need to parse this. This is done by the following main Function. For which we need another import, to read the Fileinfo as of type Text
import qualified Data.Text.IO as T(readFile)
main :: IO ()
main = do fileContents <- T.readFile "input.txt"
let result = P.parseOnly multiLines fileContents
case result of (Left s) -> putStrLn s
(Right rs) -> sequence_ (map (putStrLn . show) rs)
The parse result will get us either an error message or all NounClauses in a list. I use sequence_ (map (putStrLn .show) to print it.
You have the function show, which can convert your data type into a String because you added the deriving Show at the end of the definition if you want to use your own String representation instantiate the type class yourself (instead of your convert function) like:
instance Show NounClause where
show n = ...

How can I define a Lispy datatype in Haskell?

I'm programming a Lispy PDDL parser for the AI Planning class at Coursera.
How can I define a Lispy datatype in Haskell?
It looks Lispy, doesn't it?
{-# LANGUAGE FlexibleInstances #-}
import Data.List
data S s = T s | S [S s] deriving (Eq)
instance Show (S String) where
show (T s) = s
show (S list) = "(" ++ (intercalate " " $ map show list) ++ ")"
sExpr = S [T "define",T "x",T "10",S [T "print",T "hello"],S []]
main = do
putStrLn $ show sExpr
The result of running main:
(define x 10 (print hello) ())
My Lispy PDDL Parser:
https://dl.dropbox.com/u/46434672/Code/LispyPddlParser.hs
The DWR-operators.txt file:
https://spark-public.s3.amazonaws.com/aiplan/resources/DWR-operators.txt

Resources