Where to put code responsible with value extraction from various functors - haskell

Given a functor and given a specific way you want to unwrap its value , is there a predefined typeclass that you should implement to unwrap it?
For example given a type: data X = X Int Int where can i specialize the unwrapping of a Maybe X?
Lets say i have a a = Just (X 2 3) and i want to unwrap it the in a custom way:
(Just 2 3)-> 2^3
Nothing -> 0
But i also want to use the same method/interface to unwrap another type like a Maybe (Int,Int) like:
Just (x, y) -> x + y
Nothing -> 0
The question is more about organisation:
Is there a typeclass method where i can implement for unwrapping a Maybe X,Maybe Y, Either Z, Either K, etc.?
Or do i have to provide ungrouped (not a typeclass method instance) methods for each type that i want to unwrap from the functor?

Related

Can't understand a simple Haskell function?

Can someone explain to me step by step what this function means?
select :: (a->a->Bool) -> a -> a -> a
As the comments pointed out, this is not a function definition, but just a type signature. It says, for any type a which you are free to choose, this function expects:
A function that takes two values of type a and gives a Bool
Two values of type a
and it returns another value of type a. So for example, we could call:
select (<) 1 2
where a is Int, since (<) is a function that takes two Ints and returns a Bool. We could not call:
select isPrefixOf 1 2
because isPrefixOf :: (Eq a) => [a] -> [a] -> Bool -- i.e. it takes two lists (provided that the element type supports Equality), but numbers are not lists.
Signatures can tell us quite a lot, however, due to parametericity (aka free theorems). The details are quite techincal, but we can intuit that select must return one of its two arguments, because it has no other way to construct values of type a about which it knows nothing (and this can be proven).
But beyond that we can't really tell. Often you can tell almost certainly what a function does by its signature. But as I explored this signature, I found that there were actually quite a few functions it could be, from the most obvious:
select f x y = if f x y then x else y
to some rather exotic
select f x y = if f x x && f y y then x else y
And the name select doesn't help much -- it seems to tell us that it will return one of the two arguments, but the signature already told us that.

Haskell Either with fixed types

I have two types, assume they both have monoid implementations. Is there a way to have another type that will be specified to contain an X or a Y? Or is this not the right way to go about this?
data X = X [Int]
data Y = Y Double
The OP has clarified in the comments that they want 'instance behaviour' for some type Either X Y. Typically, you'd use a newtype in this situation:
newtype EitherXY = EitherXY (Either X Y)
In case you're not already aware, newtypes can have a record-like unwrapping function.
newtype EitherXY = EitherXY { unwrap :: Either X Y } deriving (...)
You may also auto-derive certain type classes (as with data declarations). The set of derivable classes depends on the compiler version and the set of enabled extensions. I won't elaborate on it here.
It's probably better to just do
data X_Or_Y = InX X | InY Y
This type is isomorphic to Either X Y, but it's easier to work with/pattern match on than a newtype, since it only has 2 layers of nested constructors

Haskell: when to use type class and when to use concrete type?

When declaring functions, we could either use type class or concrete type(Am I right?) So I can use "Num" as type indicator or "Int". I'm not sure if "Int" has any definition out of "Num"? Can I define my own concrete type that "inherit" from "Num"?
I ask this question from java/C# inheritance perspective, just begin with Haskell. Would you give some hints?
From the OO perspective, a type class is something like an interface or a trait. In Haskell you generally use concrete types when you require a certain structure of the datatype (because you will unpack it), and a type class when you just want a certain behavior. For example, you can write
f :: Int -> Int -> Int
f x y = x + y
but you do not use the internal structure of Ints here; you just need something that supports addition, which is Num (note that it has a (+) in method list):
f :: Num a => a -> a -> a
f x y = x + y
And yes, of course, you can declare that your own class supports the Num interface. Look at the link above, there is a list of methods called "minimal complete definition". This is what other functions that use it will rely on. In a pinch, you may explicitly set some methods to undefined, but you'll get a runtime error if someone tries to call them:
data MyData = MyData Int Int
instance Num MyData where
(MyData x1 y1) + (MyData x2 y2) = MyData (x1 + y1) (x2 + y2)
(*) = undefined
...
See how you use your knowledge of MyData structure to abstract possible users of your class from it? If they want to add two values of this type together, they do not need to know how the data is arranged inside, they just need to know that it is an instance of Num.

What is the Maybe type and how does it work?

I am just starting to program in Haskell, and I came across the following definition:
calculate :: Float -> Float -> Maybe Float
Maybe a is an ordinary data type defined as:
data Maybe a = Just a | Nothing
There are thus two possibilities: or you define a value of type a as Just a (like Just 3), or Nothing in case the query has no answer.
It is meant to be defined as a way to define output for non-total functions.
For instance: say you want to define sqrt. The square root is only defined for positive integers, you can thus define sqrt as:
sqrt x | x >= 0 = Just $ ...
| otherwise = Nothing
with ... a way to calculate the square root for x.
Some people compare Nothing with the "null pointer" you find in most programming languages. By default, you don't implement a null pointer for data types you define (and if you do, all these "nulls" look different), by adding Nothing you have a generic null pointer.
It can thus be useful to use Maybe to denote that it is possible no output can be calculated. You could of course also error on values less than 0:
sqrt x | x >= 0 = Just $ ...
| otherwise = error "The value must be larger or equal to 0"
But errors usually are not mentioned in the type signature, nor does a compiler have any problem if you don't take them into account. Haskell is also shifting to total functions: it's better to always try at least to return a value (e.g. Nothing) for all possible inputs.
If you later want to use the result of a Maybe a, you for instance need to write:
succMaybe :: Maybe Int -> Maybe Int
succMaybe (Just x) = Just (x+1)
succMaybe _ = Nothing
But by writing Just for the first case, you somehow warn yourself that it is possible that Nothing can occur. You can also get rid of the Maybe by introducing a "default" value:
justOrDefault :: a -> Maybe a -> a
justOrDefault _ (Just x) = x
justOrDefault d _ = d
The builtin maybe function (note the lowercase), combines the two previous functions:
maybe :: b -> (a -> b) -> Maybe a -> b
maybe _ f (Just x) = f x
maybe z _ Nothing = z
So you specify a b (default value) together with a function (a -> b). In case Maybe a is Just x, the function is applied to it and returned, in case the input value is Nothing, the default value will be used.
Working with Maybe a's can be hard, because you always need to take the Nothing case into account, to simplify this you can use the Maybe monad.
Tom Schrijvers also shows that Maybe is the successor function in type algebra: you add one extra value to your type (Either is addition and (,) is the type-algebraic equivalent of multiplication).

How to work around F#'s type system

In Haskell, you can use unsafeCoerce to override the type system. How to do the same in F#?
For example, to implement the Y-combinator.
I'd like to offer a different solution, based on embedding the untyped lambda calculus in a typed functional language. The idea is to create a data type that allows us to change between types α and α → α, which subsequently allows to escape the restrictions of a type system. I'm not very familiar with F# so I'll give my answer in Haskell, but I believe it could be adapted easily (perhaps the only complication could be F#'s strictness).
-- | Roughly represents morphism between #a# and #a -> a#.
-- Therefore we can embed a arbitrary closed λ-term into #Any a#. Any time we
-- need to create a λ-abstraction, we just nest into one #Any# constructor.
--
-- The type parameter allows us to embed ordinary values into the type and
-- retrieve results of computations.
data Any a = Any (Any a -> a)
Note that the type parameter isn't significant for combining terms. It just allows us to embed values into our representation and extract them later. All terms of a particular type Any a can be combined freely without restrictions.
-- | Embed a value into a λ-term. If viewed as a function, it ignores its
-- input and produces the value.
embed :: a -> Any a
embed = Any . const
-- | Extract a value from a λ-term, assuming it's a valid value (otherwise it'd
-- loop forever).
extract :: Any a -> a
extract x#(Any x') = x' x
With this data type we can use it to represent arbitrary untyped lambda terms. If we want to interpret a value of Any a as a function, we just unwrap its constructor.
First let's define function application:
-- | Applies a term to another term.
($$) :: Any a -> Any a -> Any a
(Any x) $$ y = embed $ x y
And λ abstraction:
-- | Represents a lambda abstraction
l :: (Any a -> Any a) -> Any a
l x = Any $ extract . x
Now we have everything we need for creating complex λ terms. Our definitions mimic the classical λ-term syntax, all we do is using l to construct λ abstractions.
Let's define the Y combinator:
-- λf.(λx.f(xx))(λx.f(xx))
y :: Any a
y = l (\f -> let t = l (\x -> f $$ (x $$ x))
in t $$ t)
And we can use it to implement Haskell's classical fix. First we'll need to be able to embed a function of a -> a into Any a:
embed2 :: (a -> a) -> Any a
embed2 f = Any (f . extract)
Now it's straightforward to define
fix :: (a -> a) -> a
fix f = extract (y $$ embed2 f)
and subsequently a recursively defined function:
fact :: Int -> Int
fact = fix f
where
f _ 0 = 1
f r n = n * r (n - 1)
Note that in the above text there is no recursive function. The only recursion is in the Any data type, which allows us to define y (which is also defined non-recursively).
In Haskell, unsafeCoerce has the type a -> b and is generally used to assert to the compiler that the thing being coerced actually has the destination type and it's just that the type-checker doesn't know it.
Another, less common use, is to reinterpret a pattern of bits as another type. For example an unboxed Double# could be reinterpreted as an unboxed Int64#. You have to be sure about the underlying representations for this to be safe.
In F#, the first application can be achieved with box |> unbox as John Palmer said in a comment on the question. If possible use explicit type arguments to make sure that you don't accidentally have the wrong coercion inferred, e.g. box<'a> |> unbox<'b> where 'a and 'b are type variables or concrete types that are already in scope in your code.
For the second application, look at the BitConverter class for specific conversions of bit-patterns. In theory you could also do something like interfacing with unmanaged code to achieve this, but that seems very heavyweight.
These techniques won't work for implementing the Y combinator because the cast is only valid if the runtime objects actually do have the target type, but with the Y combinator you actually need to call the same function again but with a different type. For this you need the kinds of encoding tricks mentioned in the question John Palmer linked to.

Resources