Reputation: 50
Is it possible to have a type preform a function one of its value to generate another one of it's values? For instance:
data Foo=Foo {valueOne::Int, valueTwo=valueOne*2} deriving (Bar)
Or am I thinking about this in the wrong way? Any help is appreciated!
Upvotes: 1
Views: 54
Reputation: 116174
If you always want the second field to depend on the first, just write a plain function:
data Foo = Foo { valueOne :: Int } deriving (Bar)
valueTwo :: Foo -> Int
valueTwo x = valueOne x * 2
The only difference is that the Bar
instance, which is automatically generated, won't notice the second field.
If, instead, you want to generate values with such constraint, but still be able to sometimes disregard that, use a smart constructor:
data Foo = Foo { valueOne :: Int, valueTwo :: Int } deriving (Bar)
foo :: Int -> Foo
foo x = Foo x (2 * x)
If you use foo
instead of Foo
to construct new values, you will not need to pass the second argument, which will be derived from the first one.
Usually this is used in a module
which does not export the constructor Foo
, but exports the smart constructor foo
. In this way the users of the module are constrained to build values satisfying the invariant, while the functions in the module can ignore it, when needed.
Upvotes: 9