Here is my datatype:
data Foo a = Value Integer
|Boo a
and I have a function for converting the Foo datatype to String:
showFoo::Show a=> Foo a -> String
showFoo (Value n) = show n
showFoo (Boo a) = show a
For example: showFoo (Value 10) becomes: "10", but for showFoo(Boo "S"), it becomes: "\"S\"" but I need only "S".
This boils down to the behaviour of show with strings.
show is designed to give machine-readable output, it's not a pretty-printer,
so it puts inverted commas round all strings. That way it can tell the
difference between 10 and "10" when it's reading them back in.
Your showFoo function is clearly not designed to be in the show family,
since it obliterates the Value and Boo tags, so using show isn't really what
you mean.
Possible solutions:
Give in, go the whole hog and derive Show.
If a is always a String, change your data type and don't use show.
Learn about type classes some more and define your own Showish class.
Use -XFlexibleInstances and -XOverlappingInstances to override
the instance for String, and don't use quotes.
Hack it by using init.tail.show $ a
That's just a result of you using GHCi and it showing the previous result. Try this in a compiled program or try running (in GHCi) putStrLn (showFoo (Boo "S")) and you will see that calling show on a string results in a single set of quotes.
Related
Again stuck on something probably theoretical. There are many libraries in Haskell, i'd like to use less as possible. If I have a type like this:
data Note = Note { _noteID :: Int
, _noteTitle :: String
, _noteBody :: String
, _noteSubmit :: String
} deriving Show
And use that to create a list of [Note {noteID=1...}, Note {noteID=2...}, ] et cetera. I now have a list of type Note. Now I want to write it to a file using writeFile. Probably it ghc will not allow it considering writeFile has type FilePath -> String -> IO (). But I also want to avoid deconstructing (writeFile) and constructing (readFile) the types all the time, assuming I will not leave the Haskell 'realm'. Is there a way to do that, without using special libs? Again: thanks a lot. Books on Haskell are good, but StackOverflow is the glue between the books and the real world.
If you're looking for a "quick fix", for a one-off script or something like that, you can derive Read in addition to Show, and then you'll be able to use show to convert to String and read to convert back, for example:
data D = D { x :: Int, y :: Bool }
deriving (Show, Read)
d1 = D 42 True
s = show d1
-- s == "D {x = 42, y = True}"
d2 :: D
d2 = read s
-- d2 == d1
However, please, please don't put this in production code. First, you're implicitly relying on how the record is coded, and there are no checks to protect from subtle changes. Second, the read function is partial - that is, it will crash if it can't parse the input. And finally, if you persist your data this way, you'll be stuck with this record format and can never change it.
For a production-quality solution, I'm sorry, but you'll have to come up with an explicit, documented serialization format. No way around it - in any language.
I am using the mysql-haskell package. The result of a query is of type IO [[MySQLValue]].
Now accessing the third value of a row like in the code below will print out "MySQLInt16U 5":
test2 (x:xs) = show $ x!!2
How can I "convert" those MySQLValues to Integers, Strings or other native types (In this case the type should be Int)?
EDIT: link reference for decoding types
I wrote the hsexif library and I would now add a feature, but I'm not sure how to prepare the API.
I have the ExifValue type. A ExifValue can be among others a ExifRational, which has a numerator and a denominator. Often you want to display that value (show) as "num/den", for instance for an exposition time of 1/160.
However sometimes you want to show it as a floating-point number, for instance for the exposure compensation, which you would display as "-0.75" for instance, or the aperture ("6.3").
So I want to add a function:
formatAsFloatingPoint :: ExifValue -> Int -> String
The function takes the exif value and the number of floating points after the comma to output in the result string, and returns the formatted string.
However the function will then accept any ExifValue and the user will get a runtime error and no compile time warning if it gives a ExifText as a parameter to that function...
How would I go to make a clean and type-safe API in this case?
You need to think about how you expect this to be used.
The caller might always know they have an ExifRational and will only call formatAsFloatingPoint with such a value. In that case it would make sense to refactor your datatype:
data Rational = Rational !Int !Int
data ExifValue = ... | ExifRational Rational | ...
(or perhaps reuse some existing type for expressing rationals)
and then make formatAsFloatingPoint take a Rational:
formatAsFloatingPoint :: Rational -> Int -> String
This moves the responsibility to the caller to decide when to call it.
Alternatively, perhaps callers just want to display an arbitrary ExifValue, but with special behaviour if the value happens to be an ExifRational. In that case, just use a catch-all case, e.g.:
formatAsFloatingPoint :: ExifValue -> Int -> String
formatAsFloatingPoint n (ExifRational num den) = ...
formatAsFloatingPoint _ v = show v
There are more complicated approaches based on using a type parameter to flag what kind of thing you have, but that would involve refactoring the entire library and there's little evidence that's warranted here. If you have a more general problem across the codebase of wanting to signal that you have specific kinds of ExifValue, they might make sense.
For the representation of a DSL syntax tree I have data types that represent this tree. At several places, within this tree I get quite a number of subelements that are optional and/or have a "*" multiplicity. So one data type might look something like
data SpecialDslExpression = MyExpression String [Int] Double [String] (Maybe Bool)
What I am looking for is a possibility to construct such a type without having to specify all of the parameters, assuming I have a valid default for each of them. The usage scenario is such that I need to create many instances of the type with all kinds of combinations of its parameters given or omitted (most of the time two or three), but very rarely all of them. Grouping the parameters into subtypes won't get me far as the parameter combinations don't follow a pattern that would have segmentation improve matters.
I could define functions with different parameter combinations to create the type using defaults for the rest, but I might end up with quite a number of them that would become hard to name properly, as there might be no possibility to give a proper name to the idea of createWithFirstAndThirdParameter in a given context.
So in the end the question boils down to: Is it possible to create such a data type or an abstraction over it that would give me something like optional parameters that I can specify or omit at wish?
I would suggest a combinations of lenses and a default instance. If you are not already importing Control.Lens in half of your modules, now is the time to start! What the heck are lenses, anyway? A lens is a getter and a setter mashed into one function. And they are very composable. Any time you need to access or modify parts of a data structure but you think record syntax is unwieldy, lenses are there for you.
So, the first thing you need to do – enable TH and import Control.Lens.
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
The modification you need to do to your data type is adding names for all the fields, like so:
data SpecialDslExpression = MyExpression { _exprType :: String
, _exprParams :: [Int]
, _exprCost :: Double
, _exprComment :: [String]
, _exprLog :: Maybe Bool
} deriving Show
The underscores in the beginning of the field names are important, for the following step. Because now we want to generate lenses for the fields. We can ask GHC to do that for us with Template Haskell.
$(makeLenses ''SpecialDslExpression)
Then the final thing that needs to be done is constructing an "empty" instance. Beware that nobody will check statically that you actually fill all the required fields, so you should preferably add an error to those fields so you at least get a run-time error. Something like this:
emptyExpression = MyExpression (error "Type field is required!") [] 0.0 [] Nothing
Now you are ready to roll! You cannot use an emptyExpression, and it will fail at run-time:
> emptyExpression
MyExpression {_exprType = "*** Exception: Type field is required!
But! As long as you populate the type field, you will be golden:
> emptyExpression & exprType .~ "Test expression"
MyExpression { _exprType = "Test expression"
, _exprParams = []
, _exprCost = 0.0
, _exprComment = []
, _exprLog = Nothing
}
You can also fill several fields at once, if you want to.
> emptyExpression & exprType .~ "Test expression"
| & exprLog .~ Just False
| & exprComment .~ ["Test comment"]
MyExpression { _exprType = "Test expression"
, _exprParams = []
, _exprCost = 0.0
, _exprComment = ["Test comment"]
, _exprLog = Just False
}
You can also use lenses to apply a function to a field, or look inside a field of a field, or modify any other existing expression and so on. I definitely recommend taking a look at what you can do!
Alright I'll actually expand upon my comment. Firstly, define your data type as a record (and throw in a few type synonyms).
data Example = E {
one :: Int,
two :: String,
three :: Bool,
four :: Double
}
next you create a default instance
defaultExample = Example 1 "foo" False 1.4
and then when a user wants to tweak a field in the default to make their own data they can do this:
myData = defaultExample{four=2.8}
Finally, when they want to pattern match just one item, they can use
foo MyData{four=a} = a
I'm aware of partial updates for records like :
data A a b = A { a :: a, b :: b }
x = A { a=1,b=2 :: Int }
y = x { b = toRational (a x) + 4.5 }
Are there any tricks for doing only partial initialization, creating a subrecord type, or doing (de)serialization on subrecord?
In particular, I found that the first of these lines works but the second does not :
read "A {a=1,b=()}" :: A Int ()
read "A {a=1}" :: A Int ()
You could always massage such input using a regular expression, but I'm curious what Haskell-like options exist.
Partial initialisation works fine: A {a=1} is a valid expression of type A Int (); the Read instance just doesn't bother parsing anything the Show instance doesn't output. The b field is initialised to error "...", where the string contains file/line information to help with debugging.
You generally shouldn't be using Read for any real-world parsing situations; it's there for toy programs that have really simple serialisation needs and debugging.
I'm not sure what you mean by "subrecord", but if you want serialisation/deserialisation that can cope with "upgrades" to the record format to contain more information while still being able to process old (now "partial") serialisations, then the safecopy library does just that.
You cannot leave some value in Haskell "uninitialized" (it would not be possible to "initialize" it later anyway, since Haskell is pure). If you want to provide "default" values for the fields, then you can make some "default" value for your record type, and then do a partial update on that default value, setting only the fields you care about. I don't know how you would implement read for this in a simple way, however.