Let's say I have the following datatype
data A = A{x::Int,y::Int,z::Int}
Is there a way to apply 0 on all the fields to get something like this :
let a = A 0 0 0
Basically not repeating 0
The goal at the end would be to use mempty
from Sum Int
and do something like this :
let a = myfunction mempty :: Sum Int
and Have a == A 0 0 0
Thanks !
When you define the database fields, you select a data type for each field. The data type tells Content Manager OnDemand what kind of data can be stored in the field. For search fields, in which users enter values to construct queries For display fields, to identify the items in the document list
Data can also be constant or variable within programs and functions. In a program, data values can be constant or variable. If values are variable they can be changed by the program and the user. When a program is run, the data values are held in memory whilst they are being worked on.
The following example declares the Public constant conAge as an Integer and assigns it the value 34. Constants can be declared as one of the following data types: Boolean, Byte, Integer, Long, Currency, Single, Double, Date, String, or Variant.
Public Const conAge As Integer = 34 Constants can be declared as one of the following data types: Boolean, Byte, Integer, Long, Currency, Single, Double, Date, String, or Variant. Because you already know the value of a constant, you can specify the data type in a Const statement. You can declare several constants in one statement.
There isn't one function, but you can compose Control.Monad.join
with itself. You also have to unpack the 0
from mempty
first, since it has type Sum Int
, not Int
.
let a = (join . join) A (getSum mempty)
You could then define myfunction
has
myfunction = (join . join) A . getSum
and write
let a = myfunction (mempty :: Sum Int)
The more direct definition of myfunction
, though, would simply be
myfunction (Sum x) = A x x x
Since coincidentally Data.Default
defines 0
as the default value for Int
, you can use data-default-class
to derive it generically with DeriveAnyClass
:
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
import Data.Default (Default(..))
import GHC.Generics (Generic(..))
data A = A { x, y, z :: Int }
deriving (Default, Generic)
-- (def :: A) == A 0 0 0
You can make this more explicit with DerivingStrategies
and enforce it with -Wmissing-deriving-strategies
:
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DeriveGeneric #-}
{-# OPTIONS_GHC -Wmissing-deriving-strategies #-}
import Data.Default (Default(..))
import GHC.Generics (Generic(..))
data A = A { x, y, z :: Int }
deriving (Default, Generic)
deriving anyclass (Default)
deriving stock (Generic)
-- (def :: A) == A 0 0 0
However, Data.Default
is a class with no laws; it’s better used to indicate the canonical default value of a more complex configuration-like type, because its choices for primitive types are essentially arbitrary.
So if you are able to change the type a bit, you can alternatively use the generic-deriving
package, in one of two ways. First, by using Sum Int
as the type of the fields and deriving Semigroup
and Monoid
instances with generics:
{-# LANGUAGE DeriveGeneric #-}
import Generics.Deriving.Monoid
data A = A { x, y, z :: Sum Int }
deriving (Generic)
instance Monoid A where mempty = memptydefault
instance Semigroup A where (<>) = sappenddefault
-- (mempty :: A) == A 0 0 0
-- A 1 2 3 <> A 4 5 6 == A 5 7 9
Or second—and this is my preference—by replacing the data
type with a newtype
over a tuple of Int
s, and using DerivingVia
to derive the instance via Sum Int
:
{-# LANGUAGE DerivingVia #-}
newtype A = A (Int, Int, Int)
deriving (Monoid, Semigroup) via (Sum Int, Sum Int, Sum Int)
-- (mempty :: A) == A 0 0 0
-- A 1 2 3 <> A 4 5 6 == A 5 7 9
You can recover the field names using lenses (e.g. x
is _1
) or by writing getters and setters manually.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With