Haskell. Why does read function does not work with custom data type though I used deriving? - haskell

Read function does not work properly with custom data type.
data TwoInts = Int Int
deriving (Read, Show)
conv :: String -> TwoInts
conv s = read s
When i load this function with ghci
ghci conv.hs
It loads properly, but when i call it
conv "15 14"
i am getting following error:
*** Exception: Prelude.read: no parse

As suggested, your data type:
data TwoInts = Int Int
deriving (Read, Show)
describes a constructor named Int that accepts a type Int. If you were to use records, maybe this is more clear:
data TwoInts = Int { int :: Int}
deriving (Read, Show)
The solution as suggested in the comments is to name your constructor something else, e.g.,
data TwoInts = TwoInts Int Int
deriving (Read, Show)

Related

Haskells data types and constructors with functions?

I'm new to Haskell and I'm looking at basic data types and constructors with functions.
I've done the below code:
data Name = Name String deriving (Show)
data Age = Age Int deriving (Show)
data Iq = Iq Int deriving (Show)
data Language = Language String deriving (Show)
data DataSubject = DSInformation Name Age Iq Language | DSConstruct {name :: String, age :: Int, iq :: Int, language :: String} deriving (Show)
makeDataSubject :: DataSubject -> DataSubject --Take in info and output a record
makeDataSubject (DSInformation (Name n) (Age a) (Iq i) (Language l)) = (DSConstruct {name = n, age = a, iq = i, language = l})
main = do
let x = makeDataSubject $ (DSInformation (Name "Ron") (Age 34) (Iq 100) (Language "French"))
putStrLn $ show x
Runs fine, however it seems overly verbose -- how can I make to make it better?
Most of your data declarations can probably be simple type aliases.
type Name = String
type Age = Int
type Iq = Int
type Language = String
With these aliases, there is no significant difference (record syntax aside) between the two constructors for DataSubject. Get rid of one, and dispense with makeDataSubject. (Unless you want to encapsulate some logic or prevent pattern matching, you don't need a smart constructor to do what you are doing.)
data DataSubject = DS { name :: Name
, age :: Age
, iq :: Iq
, language :: Language
} deriving (Show)
main = do
let x = DS { name="Ron", age=34, iq=100, language="French"}
putStrLn $ show x
If you do want real types, not just aliases, use newtype instead of data.
newtype Name = Name String deriving Show
newtype Age = Age Int deriving Show
newtype Iq = Iq Int deriving Show
newtype Language = Language String deriving Show
data DataSubject = DS { name :: Name
, age :: Age
, iq :: Iq
, language :: Language
} deriving (Show)
main = do
let x = DS { name=Name "Ron", age=Age 34, iq=Iq 100, language=Language "French"}
putStrLn $ show x
You might want to add a smart constructor here, but have it take each piece of data as a separate argument (wrapped or unwrapped), not a single argument that is already the return value up to isomorphism. (That is, your constructor was essentially the identity function other than some repackaging of the input.)
makeDataSubject :: String -> Int -> Int -> String -> DataSubject
makeDataSubject name age iq lang = DS {name=Name name, age=Age age, iq=Iq iq, language=Language lang}
or
makeDataSubject' :: Name -> Age -> Iq -> Language -> DataSubject
makeDataSubject' name age iq lang = DS {name=name, age=age, iq=iq, language=lang}
Unfortunately you are running into one of Haskell's weaknesses: the record system. It would be nice if we had some sort notation to express subject.name and subject.age rather than destructuring explicitly but right now there is no good answer. Work coming down the pipeline in GHC 8 should address the problem soon, however, and there are are all sorts of libraries working in the problem space. But, for this question specifically, we can employ a simple trick: -XRecordWildcards.
{-# LANGUAGE RecordWildCards #-}
module Main where
newtype Name = Name String deriving Show
newtype Age = Age Int deriving Show
newtype Iq = Iq Int deriving Show
newtype Language = Language String deriving Show
data DataSubject =
DSInformation Name Age Iq Language
| DSConstruct {name :: String, age :: Int, iq :: Int, language :: String}
deriving Show
-- | Take in info and output a record
makeDataSubject :: DataSubject -> DataSubject
makeDataSubject (DSInformation (Name name) (Age age) (Iq iq) (Language language)) =
DSConstruct {..}
main :: IO ()
main =
print . makeDataSubject $ DSInformation (Name "Ron") (Age 34) (Iq 100) (Language "French")
By destructuring into the names of the fields, {..} will pick up on those bindings in scope to automatically populate the fields. You will absolutely want to turn on -Wall -Werror during compilation because it will be now more than ever easier to misspell something and forget to populate a field and then you end up with a partial record (another wart of the records system) where some fields are left undefined.

Haskell, unnamed command line arguments for optparse-generic

I'm using optparse-generic to parse the command line arguments of a program called example. I have a datatype with named fields (record syntax). For example:
data Example = Example { foo :: Int, bar :: String } deriving (Generic, Show)
This generates a program which can be called as follows:
./example --foo 42 --bar "baz"
How can I tell optparse-generic that bar should be an unnamed, mandatory, positional command line argument. That means, I don't want to type --bar when I call example. For example, I want to call example the following:
./example --foo 42 "baz"
optparse-generic does not support generating such a parser from a single data type definition since Haskell does not support records with both labeled and unlabeled fields.
However, what you can do is generate one data type for all the labeled fields and one type for the unlabeled fields and then combine them using Applicative operations, like this:
data Labeled = Labeled { foo :: Int } deriving (Generic, Show)
instance ParseRecord Labeled
data Unlabeled = Unlabeled String deriving (Generic, Show)
instance ParseRecord Unlabeled
data Mixed = Mixed Labeled Unlabeled deriving (Show)
instance ParseRecord Mixed where
parseRecord = Mixed <$> parseRecord <*> parseRecord

Data type without input value and multiple primitive types

Firstly, I'd like to apologize if I'm repeating this but I searched everywhere without finding an answer to my question.
Suppose I have the following code:
data TestType = Nothing | Int | Float deriving (Show)
jaykay :: TestType -> [Char]
jaykay Int = "This is an int"
jaykay Float = "This is float!"
jaykay a = "Nothing matched.."
main :: IO()
main = do
jaykay [PLACE HOLDER]
Clearly this type does not have any value constructor(s). So what I thought I could do here is create a type from primitive types that would normally hold any values of the specified ones in the definition right? My question is about how would I construct an instance of this type and also if this definition isn't correct how would I achieve what I described earlier?
Thanks
Actually, your type does have value constructors -- three of them, in fact, named Nothing, Int, and Float. So, one could write, for example
main = putStrLn (jaykay Int)
and running the program would print out This is an int. However, I suspect that you wanted your constructors to accept arguments of the related types; so you probably wanted to write something like
data TestType = Nothing | Int Int | Float Float
so that values of type TestType constructed with the Int constructor would contain an additional value of type Int; and likewise those constructed with the Float constructor would contain a value of type Float. (N.B. there are two separate namespaces here! There is a type-level name Int which comes from the Prelude and you have now also defined a value-level Int whose type is Int -> TestType.)
An example of using this more exciting new data type would be this:
jaykay (Int i) = "got the Int " ++ show i
jaykay (Float f) = "got the Float " ++ show f
jaykay a = "dunno lol"
main = putStrLn (jaykay (Int 3))
Running this program would print out got the Int 3.

Convert Lens' a b into Lens' a (Maybe b)

I have several data structures like
data Data1 = Data1
{ _data1Field :: Int
-- More fields
} deriving (Eq, Show)
makeLenses ''Data1
data Data2 = Data2
{ _data2Field :: Int
-- More fields
} deriving (Eq, Show)
makeLenses ''Data2
-- More similar data types
So I decided to write a simple type class to make it easier to compose
class HasField a where
field :: Lens' a Int
instance HasField Data1 where
field = data1Field
instance HasField Data2 where
field = data2Field
But then I ran into the problem that some of these structures have the corresponding field as optional
data Data3 = Data3
{ _data3Field :: Maybe Int
-- More fields
} deriving (Eq, Show)
makeLenses ''Data3
And now I can no longer use the type class. Since there are about the same number of data types that have that field optional as not, I decided that it'd be better to change the typeclass:
class HasField a where
field :: Lens' a (Maybe Int)
instance HasField Data3 where
field = data3Field
But since I'm not very experienced with the lens library, I'm stuck figuring out how to make this new lens work with the types for Data1 and Data2. Ideally, I'd like to be able to view it and get a Maybe Int value for any type, and when setting I'd like Just x to set the field to x for Data1 and Data2 and be a no-op for those two types when passed Nothing.
Is this possible using existing combinators or am I going to have to write the lens myself? I'm fine doing so, but the majority of existing tutorials use TH and gloss over the details of writing one by hand.
I'm using GHC 7.6.3 and lens 3.10.
As a follow up to shachaf
class HasFieldA d where
field :: Traversal' d Int
instance HasFieldA Data1 where
field = data1Field -- Lens's are Traversals
instance HasFieldA Data3 where
field = data3Field . _Just
And then the ^? operator or the ^.. operator
getField :: HasFieldA d => d -> Maybe Int
getField = d ^? field -- or preview field d
to get it.
To set optional fields, you'd need another function
class SetFieldA d where
setField :: Setter' d Int
instance SetFieldA Data3 where
setField = set data3Field . Just

Not in scope: data constructor in Haskell

Please tell me what is the problem?
data Stack' v = Stack' [v] Int deriving (Show)
...
type StackInt = Stack' Int
main = print(StackInt [1,2,3] 4)
The error i am getting is
Not in scope: data constructor `Stackint'
What is wrong?
It looks to me like you are confusing the concepts of types and constructors, this is a common problem as they live in separate namespaces and are often given the same name. In the Haskell expression
data SomeType = SomeType Int
say, you are actually defining the type SomeType and a constructor SomeType. The type is not a function in the normal sense, but the constructor is. If you asked ghci for the type of SomeType you would get this:
:t SomeType
SomeType :: Int -> SomeType
Now, a type declaration is just a shorthand for a longer type definition, in your case making StackInt a synonym of Stack' Int. But in order to construct a value of this type you still need to use the constructor Stack' (which has type [v] -> Int -> Stack' v). So your code should be
data Stack' v = Stack' [v] Int deriving (Show)
main = print(Stack' [1,2,3] 4)
If you wanted to be sure that the type was Stack' Int then you could add a function
data Stack' v = Stack' [v] Int deriving (Show)
stackInt :: [Int] -> Int -> Stack' Int
stackInt list i = Stack' list i
main = print(stackInt [1,2,3] 4)
EDIT: Not also that I've written stackInt list i = Stack' list i for transparency here, but you can write it more elegantly just as stackInt = Stack'. It is the type constraint that makes sure that you get the right type here.
You could also have both the new function and the type synonym if you wanted, ie
data Stack' v = Stack' [v] Int deriving (Show)
type StackInt = Stack' Int
stackInt :: [Int] -> Int -> StackInt
stackInt list i = Stack' list i
main = print(stackInt [1,2,3] 4)
The name of the constructor is Stack', not StackInt. Creating a type alias using type does not create an alias for the constructors (which wouldn't make sense since there may be many constructors for the type and their names don't have to be related the type name at all).
There is no data constructor called Stackint. Stackint as defined by your type declaration is a type constructor.
The data constructor is, as for Stack', Stack', although thanks to the type synonym it'll have type Int -> Stack' Int instead of a -> Stack' a.

Resources