I've been experimenting with deriving
and had some hard time to understand how deriving (Read)
works.
Let's have a look at the following data definition:
data Data = D Int deriving (Eq, Read, Show)
data DataWithName = DWN { val :: Int } deriving (Eq, Read, Show)
Nothing special, just two data types each capsulating an Int
, but the second one introduces a the name val
for the Int
.
In the interactive console, following instructions work as expected:
*Main> D 5
D 5
*Main> DWN 5
DWN {val = 5}
*Main> DWN { val = 5 }
DWN {val = 5}
while the following one is not working (EDIT: I expected this to not work)
*Main> D { val = 5 }
<interactive>:11:1:
Constructor `D' does not have field `val'
In the expression: D {val = 5}
In an equation for `it': it = D {val = 5}
Now let's come down to it:
I thought that deriving Read
would give me the same ways how to enter a data type, but in the following line 1 and line 2 work, while line 3 does not work because the parameter name is not given:
d1 = read "D 1" :: Data -- Works
d2 = read "DWN { value = 1 }" :: DataWithName -- Works
d3 = read "DWN 1" :: DataWithName -- This does not work because parameter is not given.
Is there some possibility to enable derving (Read)
to also derive the "non-parameter-name constructor" such that read "DWN 5" :: DataWithName
would work additionally to the "parameter-name constructor"?
Or can you provide me some information on how data reading / input should be handled?
Thanks!
I thought that deriving Read would give me the same ways how to enter a data type, but in the following line 1 and line 2 work, while line 3 does not work ...
That's not what Read
does or deriving
achieve. In fact the expression D { val = 5 }
is not correct at all. val
is just another normal function you get out from the record construction. You can even inspect its type:
ghci| > :t val
val :: DataWithName -> Int
The data constructor D
only accepts Int
as it's argument as evidenced by it's type:
ghci| > :t D
D :: Int -> Data
So no matter what you do, you cannot give it something like D { val = 5 }
as it a type error.
Is there some possibility to enable deriving (Read) to also derive the "non-parameter-name constructor" such that read "DWN 5" :: DataWithName would work additionally to the "parameter-name constructor"?
No. But you can do some parsing of the String
and convert it manually to the required data structure.