Reverse data constructor - haskell

How can I define a function that will accept my type and return its primitive "synonym"? For example:
newtype MyInt = MakeInt Int
And i want a function:
unMyInt :: MakeInt -> Int

The other (and more comfortable way sometimes) is record syntax:
newtype myInt a = MyInt { unMyInt :: Int }
This automatically defines a function
unMyInt :: MyInt -> Int

By pattern matching on the constructor:
unMyInt (MakeInt i) = i

Related

Strict type alias in Haskell

Suppose I have a recursive function taking 3 integers, each having a different meaning, e.g.
func :: Int -> Int -> Int -> SomeType1 -> SomeType2
What I want is to prevent myself from mistyping the order of the arguments like this (somewhere in the func implementation):
func a b c t = f b a c ( someProcessing t )
The easiest way I've come up with is to define type aliases like
type FuncFirstArg = Int
type FuncSecondArg = Int
type FuncThirdArg = Int
And change func signature:
func :: FuncFirstArg -> FuncSecondArg -> FuncThirdArg -> SomeType1 -> SomeType2
But it seems like this approach doesn't work as I intended. Why does Haskell still allow me to pass FuncSecondArg as a first argument and so on. Is there a way to do what I want without declaring datatypes?
type in Haskell is a rename of an existing type. Just like String and [Char] are fully exchangeable, so are FuncFirstArg and Int, and by transition FuncSecondArg as well.
The most normal solution is to use a newtype which was introduced exactly for the purpose of what you try to achieve. For convenience, it is good to declare it as a record:
newtype FuncFirstArg = FuncFirstArg {unFuncFirstArg :: Int}
Note that newtype is entirely reduced during compilation time, so it has no overhead on the runtime.
However, if you have many arguments like in your example, a common strategy is to create a dedicated type for all of the parameters supplied to the function:
data FuncArgs = FuncArgs
{ funcA :: Int
, funcB :: Int
, funcC :: Int
, funcT :: Sometype1
}
f :: FuncArgs -> Sometype2
Yes, it has some bad impact on currying and partial application, but in many cases you can deal with it by providing predefined argument packs or even uncurry the function:
defaultArgs :: Sometype1 -> FuncArgs
defaultArgs t = FuncArgs {a = 0, b = 0, c = 0, t = t}
fUnc :: Int -> Int -> Int -> SomeType1 -> SomeType2
fUnc a b c t = f $ FuncArgs a b c t
Conclusion
For the typechecker to distinguish types, the types have to be actually different. You can't skip defining new types, therefore.

How to use Monadic binding operator on ADT or record syntax

Hello can someone please explain me how can you use the monadic binding operator on a field of an Algebraic Data Type or record syntax?
E.g.
data M = M {myfield :: Int}
data N = N Int
So for M if i want to extract the value from an IO Int action into myfield it seems i can't say:
a = M { return 3 >>= value }
Also how can I bind for an N type?
The field has type Int, so you can't bind it to anything of a different type, like IO Int.
You can however, run the IO Int action, get an Int back, and use that.
foo :: IO Something
foo = do
i <- return 3 -- run your (IO Int) action
let a = M { myfield = i }
...
-- at the end, you have to use an (IO Something) action
Instead you can convert N to M as follows
convertNtoM :: N -> M
convertNtoM (N i) = M { myfield = i }
This, again, does not bind a N value to myfield, but binds the integer "inside" the N value.
In the case one has several actions to run, and many fields to fill, one can use the "applicative style".
data K = K Int Int Int Int
action :: IO Int
action = return 3
foo :: IO K
foo = K <$> action <*> action <*> action <*> action

What is the right way to declare data that is an extension of another data

I am modelling a set of "things". For the most part all the things have the same characteristics.
data Thing = Thing { chOne :: Int, chTwo :: Int }
There is a small subset of things that can be considered to have an "extended" set of characteristics in addition to the base set shared by all members.
chThree :: String
I'd like to have functions that can operate on both kinds of things (these functions only care about properties chOne and chTwo):
foo :: Thing -> Int
I'd also like to have functions that operate on the kind of things with the chThree characteristic.
bar :: ThingLike -> String
I could do
data ThingBase = Thing { chOne :: Int, chTwo :: Int }
data ThingExt = Thing { chOne :: Int, chTwo :: Int, chThree :: Int }
fooBase :: ThingBase -> Int
fooExt :: ThingExt -> Int
bar :: ThingExt -> String
But this is hideous.
I guess I could use type classes, but all the boilerplate suggests this is wrong:
class ThingBaseClass a of
chOne' :: Int
chTwo' :: Int
instance ThingBaseClass ThingBase where
chOne' = chOne
chTwo' = chTwo
instance ThingBaseClass ThingExt where
chOne' = chOne
chTwo' = chTwo
class ThingExtClass a of
chThree' :: String
instance ThingExtClass ThingExt where
chThree' = chThree
foo :: ThingBaseClass a => a -> Int
bar :: ThingExtClass a => a -> String
What is the right way to do this?
One way to do so, is the equivalent of OO aggregation :
data ThingExt = ThingExt { thing :: Thing, chTree :: Int }
You can then create a class as in your post
instance ThingLike ThingExt where
chOne' = chOne . thing
chTwo' = chTwo . thing
If you are using the lens library you can use makeClassy which will generate all this boiler plate for you.
You can make a data type that is a type union of the two distinct types of things:
data ThingBase = ThingBase { chBaseOne :: Int, chBaseTwo :: Int }
data ThingExt = ThingExt { chExtOne :: Int, chExtTwo :: Int, chExtThree :: Int }
data ThingLike = CreatedWithBase ThingBase |
CreatedWithExt ThingExt
Then for any function which should take either a ThingBase or a ThingExt, and do different things depending, you can do pattern matching on the type constructor:
foo :: ThingLike -> Int
foo (CreatedWithBase (ThingBase c1 c2)) = c1 + c2
foo (CreatedWithExt (ThingExt c1 c2 c3)) = c3
-- Or another way:
bar :: ThingLike -> Int
bar (CreatedWithBase v) = (chBaseOne v) + (chBaseTwo v)
bar (CreatedWithExt v) = chExtThree v
This has the benefit that it forces you to pedantically specify exactly what happens to ThingBases or ThingExts wherever they appear to be processed as part of handling a ThingLike, by creating the extra wrapping layer of constructors (the CreatedWithBase and CreatedWithExt constructors I used, whose sole purpose is to indicate which type of thing you expect at a certain point of code).
But it has the disadvantage that it doesn't allow for overloaded names for the field accessor functions. Personally I don't see this as too big of a loss, since the extra verbosity required to reference attributes acts like a natural complexity penalty and helps motivate the programmer to keep the code sparse and use fewer bad accessor/getter/setter anti-patterns. However, if you want to go far with overloaded accessor names, you should look into lenses.
This is just one idea and it's not right for every problem. The example you already give with type classes is also perfectly fine and I don't see any good reason to call it hideous.
Just about the only "bad" thing would be wanting to somehow implicitly process ThingBases differently from ThingExts without needing anything in the type signature or the pattern matching sections of a function body to explicitly tell people reading your code precisely when and where the two different types are differentiated, which would be more like a duck typing approach which is not really what you should do in Haskell.
This seems to be what you're trying to get at by trying to force both ThingBase and ThingExt to have a value constructor with the same name of just Thing -- it seems artificially nice that the same word can construct values of either type, but my feeling is it's not actually nice. I might be misunderstanding though.
A very simple solution is to introduce a type parameter:
data ThingLike a = ThingLike { chOne, chTwo :: Int, chThree :: a }
deriving Show
Then, a ThingBase is just a ThingLike with no third element, so
type ThingBase = ThingLike ()
ThingExt contains an additional Int, so
type ThingExt = ThingLike Int
This has the advantage of using only a single constructor and only three record accessors. There is minimal duplication, and writing your desired functions is simple:
foo :: ThingLike a -> Int
foo (ThingLike x y _) = x+y
bar :: ThingExt -> String
bar (ThingLike x y z) = show $ x+y+z
One option is:
data Thing = Thing { chOne :: Int, chTwo :: Int }
| OtherThing { chOne :: Int, chTwo :: Int, chThree :: String }
Another is
data Thing = Thing { chOne :: Int, chTwo :: Int, chThree :: Maybe String }
If you want to distinguish the two Things at the type level and have overloaded accessors then you need to make use of a type class.
You could use a Maybe ThingExt field on ThingBase I guess, at least if you only have one extension type.
If you have several extensions like this, you can use a combination of embedding and matching on various constructors of the embedded data type, where each constructor represents one way to extend the base structure.
Once that becomes unmanageable, classes might become unevitable, but some kind of data type composition would still be useful to avoid duplication.

Create a haskell constructor for a new data type that takes in a function

I want to create a new data type that can take in a function.
I know this works:
foo :: (Int -> Int -> Int)->Int->Int->Int
foo func x y = (func x y) + 100
so you can do this:
foo (+) 5 8 --output is 113
Now I want to do the same thing but to a custom data type like this:
data Bar = Bar (Int Int Int) Int Int --This does not compile
so I can use it like this:
doCalc :: Bar -> Int
doCalc (Bar func x y) = (func x y) + 100
My question is how do I declare the constructor in my data type to do this?
Note that the first argument of foo is of type (Int -> Int -> Int) - the type of a function that takes two Ints and return another one. (Int Int Int) is not a legal Haskell type (since Int is a concrete type and not a type constructor, like Maybe).
Try:
data Bar = Bar (Int -> Int -> Int) Int Int
Your doCalc function is correct and will work with the new version.

Haskell data type pattern matching

Lets say you have
data SS=
SSliteral Value
and
data Value=
SSint Int
Now lets say you have n which is of type SS. You want to get the Int value of SS, how would you go about doing so?
You pattern match on n.
getIt :: SS -> Int
getIt (SSliteral (SSint x)) = x
I suggest you read lyah.
We define with record syntax:
data SS = SSliteral {
ssValue :: Value
}
data Value = SSint {
ssInt :: Int
}
now we define
getIt :: SS -> Int
getIt = ssInt . ssValue
And now we are point-free.

Resources