Haskell data type pattern matching - haskell

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.

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

Haskell function that returns arbitrary number of fields as list

I want to write a Haskell function that takes a custom type with eleven fields and returns either a list of all the fields' values, or a map associating the fields' names with their values. I don't want to have to explicitly get every field because that would be verbose and less versatile. Is there any way to do this?
What you write would be possible to some degree, but it wouldn't be very useful.
Let's imagine we insist on writing this function for a moment. Given that the fields' values may have different types, you probably rather want to yield a tuple. I.e.
data MyType = MyType Int String Bool
getFields :: MyType -> (Int, String, Bool)
getFields (MyType a b c) = (a,b,c)
So you could now call it like
let v = MyType 1 "Hello" True
let (x, y, z) = getFields v
Now, this isn't actually very useful, because you could use pattern matching in all of these cases, e.g.
let v = MyType 1 "Hello" True
let (MyType x y z) = v
Alright, but what if you wanted to address individual fields? Like
let x = fst (getFields v)
...how to do that without a 'getFields' function? Well, you can simply assign field names (as you probably already did):
data MyType = MyType
{ i :: Int
, s :: String
, b :: Bool
}
Now you could functions for accessing indivial fields for free:
let x = i v
...since assigning names ot fields actually generates functions like i :: MyType -> Int or s :: MyType -> String.

Find a datatype in list by comparing first value in haskell

I have a list of data types and I want to find the one that matches the first value, if it exists. If it does not exist, I want to return a default value.
data MyType = MyType String Int
findOrMake :: [MyType] -> String -> Int
findOrMake list x = do i <- -- find index
-- if i is a value, return the x[i]
-- if i is not a value, return (MyType x 0)
I have an intuition that I should use fmap and find, but I have never used either before.
How about a simple recursive solution?
data MyType = MyType String Int
findOrMake :: [MyType] -> String -> Int
findOrMake [] s = 42
findOrMake ((MyType mstr mint):ms) s = if mstr == s then mint else findOrMake ms s
To provide a default when the item is not found, you can use fromMaybe:
fromMaybe :: a -> Maybe a -> a
Combined with find, it should look something like this:
fromMaybe defaultValue $ find predicate list

Reverse data constructor

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

Resources