Typeclass conversion in Haskell [duplicate] - class

This question already has answers here:
Haskell - Maybe Either
(4 answers)
Closed 8 years ago.
I have this assignment where I am unsure where to start. So one of the things is to do a
maybe to either conversion with this signature:
maybeEither:: Maybe a -> Either () a
and the other is of course the opposite
eitherMaybe:: Either () a -> Maybe a
so when you call one of the other they will cancel eachother out.
Now I don't really know where to begin here... Can someone help?
Extra question: How would I convert a function for example (Int->a) -> a and a -> (Int->a)
Like since in the second example you really can't give the function as a parameter to the function that converts, Im not sure how that would go.

First of all, these are not typeclasses, they're data types. If you're unfamiliar with the difference, I would recommend reading the relevant chapters in Learn You a Haskell.
To solve this particular problem, you just need to pattern match on the different constructors:
maybeEither :: Maybe a -> Either () a
maybeEither Nothing = ???
maybeEither (Just a) = ???
And
eitherMaybe :: Either () a -> Maybe a
eitherMaybe (Left x) = ???
eitherMaybe (Right y) = ???
You just need to fill in the the ???s and you're done.
For your extra question, remember that the signature a -> (Int -> a) is the same as a -> Int -> a, since -> is right associative.

Actually it's very simple, just follow the types to see what you get. The type signature of maybeEither suggests that it takes Maybe a as input.
Maybe is defined like this:
data Maybe a = Just a | Nothing
Also, from the type sigature, you can get that maybeEither gives Either () a as the output for the function.
Either type constructor is defined like this:
data Either a b = Left a | Right b
Now, replace a with () and you will get:
Either () b = Left () | Right b
Or you can replace your type variables to make it clear,
Either () a = Left () | Right a
Now, the implementation of the function is pretty straightforward.
maybeEither :: Maybe a -> Either () a
maybeEither (Just x) = ??? -- fill these
maybeEither Nothing = ???
You can follow the same approach for your other function.

Related

Is it an example of a Monad? If not, why?

I am trying to study functional programming applied to Swift (a multi-paradigm language). One of the exercises I proposed to myself was trying to do a declarative Poker Hand evaluator.
Here are some code excerpts and my question at the end:
typealias Rule = ([Card]) -> Result
Where Result is a type that holds the current evaluation state (cards already evaluated on a rank, remaining cards, if the last rule evaluation was successful or not and the evaluated ranks). The input is an array (could be a set of) cards to be evaluated.
I also created this function:
func id(_ hand:[Card]) -> Result ...
That creates a mininum Result from a card set.
Result also have a set of functions to chain rule evaluations (simplified here):
func apply(_ rule:Rule) -> Result
func andThen(_ rule:Rule) -> Result
func andAlso(_ rule:Rule) -> Result
func otherwise(_ rule:Rule) -> Result
func continueWith(_ rule:Rule) -> Result
Whats allowed me to declare the poker rank rules as:
let fullHouse = { (hand) in
threeOfAKind(hand).andThen(pair)
}
or
let royalStraightFlush = { (hand) in
straightFlush(hand).andAlso(straightAceHigh)
}
and chaining all rank rules as:
let evaluate = { (hand) in
//id(hand)
royalStraightFlush(hand)
.otherwise(straightFlush)
.otherwise(fourOfAKind)
.otherwise(fullHouse)
.otherwise(flush)
.otherwise(straight)
.otherwise(threeOfAKind)
.otherwise(twoPair)
.otherwise(pair)
.continueWith(highCard) }
Result, as it is:
Encompasses a type ([Card]) into a broader context (R a)
Has an id (result) function that put an object of type a into a minimum "result" context (a -> R a)
But...
It has not just one generic >>= bind function, but several specific ones, that takes R a -> (a -> R a) -> R a that could chain rules and get the card set to be evaluated from the previous partial result state.
It is not (as it is implemented) generic enough to handle other types instead of Card or [Card]. In the other hand I think the same chaining logic could be used on other rule systems with some changes...
My question is: is Result a monad? Otherwise, why it is not? My two concerns are those presented above.
I think understanding these points (or knowing that are some other blind spots) on this concrete example will clarify a little bit the monad concept to me.
Thanks!
Monads have to obey the three Monad Laws:
Left identity: return a >>= f ≡ f a
Right identity: m >>= return ≡ m
Associativity: (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
This also implies the implementation of return (or equivalent) and >>= (variously called bind, flatmap, etc.) for your monad.. Haskell (and other languages) also adds the map function (>>) even though it can be implemented in terms of >>=.
In addition, as #chepner points out, monads are abstractions that are not concrete types in themselves. They are generic and can only be instantiated via a type constructor. List is a monad but you cannot instantiate a List. You can, however, instantiate a List[Int].
If you want to get a good conceptual picture of what makes a monad a monad, take a look at Brian Beckman's video Don't Fear the Monad. Also, there is a good series of blog posts, Monads are Elephants.

Why don't these types unify when using type constraints and a typeclass instance?

So, I am attempting to develop a function that expects a polymorphic function.
I start with and create a class Foo, to represent the constrained type argument in the example function.
module Test
where
class Foo a
Along with a random type for this example...
newtype Bar = Bar Int
In order to pass Bar to anything that has a Foo constraint, it needs to have a typeclass, so I do so:
instance fooBar :: Foo Bar
Everything should be perfectly fine, however, this doesn't work, psc doesn't think the types unify and I don't know why:
example :: forall a. (Foo a) => (a -> Int) -> Int
example a = a (Bar 42)
Error as follows:
Error found:
in module Test
at /Users/arahael/dev/foreign/test.purs line 11, column 16 - line 11, column 22
Could not match type
Bar
with type
a0
while checking that type Bar
is at least as general as type a0
while checking that expression Bar 42
has type a0
in value declaration example
where a0 is a rigid type variable
bound at line 11, column 1 - line 11, column 22
See https://github.com/purescript/documentation/blob/master/errors/TypesDoNotUnify.md for more information,
or to contribute content related to this error.
Compare
(1) example :: (forall a. (Foo a) => a -> Int) -> Int
with
(2) example :: forall a. (Foo a) => (a -> Int) -> Int
The latter essentially places responsibility on you, the caller, to supply as the argument to example a function (your choice!) w/ the signature a -> Int (such that there is a Foo instance for a).
The former, on the other hand, says that you, the caller, don't actually get to pick what this function a -> Int is. Rather, as Norman Ramsey has explained in a Haskell-related stackoverflow answer here, when the forall is "to the left" of the arrow (rather than "above the arrow") the implementation decides what function to supply. The signature in (2) is saying any function a -> Int will do as the argument to example (so long as there is a Foo intance for a).
If (1) just "magically" works, then, it's because the function that unwraps the newtype Bar is being selected by the compiler as perfectly satisfactory, and passed as the argument to example in case (1). After all, the signature of (1) suggests that example should return the same Int values no matter what function a -> Int is given (so long as there is a Foo instance for a). In case (2), the Int values returned by example may very well differ depending upon the specific function a -> Int supplied. The compiler cannot grab any such function that it knows satisfies the type at random. It cannot guess the type of a or a -> Int that you, the caller, actually have in mind.

Convert datatype to string (SML)

I have a function that returns a (char * int) list list, like [[(#"D", 3)], [(#"F", 7)]], and now I'm wondering if it's posssible to convert this to a string, so that I can use I/O and read it to another file?
First of all, I assume you meant a value like [[(#"D", 3)], [(#"F", 7)]] (note the extra parens) since SML requires parentheses around tuple construction. OCaml uses a slightly different syntax, and allows just commas, like a, b, to construct tuples. I mention this because what follows is totally specific to Standard ML, and doesn't apply to OCaml, because I believe that in OCaml your best bet is an entirely different approach, which I don't know much about (macros, i.e. ocamlp4/5). So I assume that was just a typo and that you're interested in Standard ML.
Now, unfortunately there is no general toString function in Standard ML. Something like that would have to have some kind special support in the language and implementation, since it's not possible to write a function with the type 'a -> string. You basically have to write your own toString : t -> string for each type t.
As you can imagine, this gets tedious fast. I've spent a little time researching the options (for this and other boilerplate functions like compare : 't * 't -> order) and there is one very interesting technique outlined in the paper "Generics for the working ML'er" (http://dl.acm.org/citation.cfm?id=1292547) but it's pretty advanced and I could never actually get the code to compile (that said the paper is very interesting) The full generics library described in that paper is in the MLton lib repo (https://github.com/MLton/mltonlib/tree/master/com/ssh/generic/unstable). Maybe you'll have better luck?
Here's a slightly lighter weight approach that is less powerful but easier to understand, IMHO. I wrote this after reading that paper and struggling to get it to work. The idea is to write building blocks for toString functions (called show in this case) and compose them with other functions for your own types.
structure Show =
struct
(* Show.t is the type of toString functions *)
type 'a t = 'a -> string
val int: int t = Int.toString
val char: char t = Char.toString
val list: 'a t -> 'a list t =
fn show => fn xs => "[" ^ concat (ExtList.interleave (map show xs) ",") ^ "]"
val pair: 'a t * 'b t -> ('a * 'b) t =
fn (showa,showb) => fn (a,b) => "(" ^ showa a ^ "," ^ showb b ^ ")"
(* ... *)
end
Since your type doesn't actually have any user defined datatypes, it's very easy to write the toString function using this structure:
local
open Show
in
val show : (char * int) list list -> string = list (list (pair (char, int)))
end
- show [[(#"D", 3)], [(#"F", 7)]] ;
val it = "[[(D,3)],[(F,7)]]" : string
What I like about this is that the composed functions read like the type turned inside out. It's a quite an elegant style, which I cannot take credit for as I took it from the generics paper linked above.
The rest of the code for Show (and a related module Eq for equality comparison) is here: https://github.com/spacemanaki/lib.sml

Defining a function a -> String, which works for types without Show?

I'd like to define a function which can "show" values of any type, with special behavior for types which actually do define a Show instance:
magicShowCast :: ?
debugShow :: a -> String
debugShow x = case magicShowCast x of
Just x' -> show x'
Nothing -> "<unprintable>"
This would be used to add more detailed information to error messages when something goes wrong:
-- needs to work on non-Showable types
assertEq :: Eq a => a -> a -> IO ()
assertEq x y = when (x /= y)
(throwIO (AssertionFailed (debugShow x) (debugShow y)))
data CanShow = CanShow1
| CanShow 2
deriving (Eq, Show)
data NoShow = NoShow1
| NoShow2
deriving (Eq)
-- AssertionFailed "CanShow1" "CanShow2"
assertEq CanShow1 CanShow2
-- AssertionFailed "<unprintable>" "<unprintable>"
assertEq NoShow1 NoShow2
Is there any way to do this? I tried using various combinations of GADTs, existential types, and template haskell, but either these aren't enough or I can't figure out how to apply them properly.
The real answer: You can't. Haskell intentionally doesn't define a generic "serialize to string" function, and being able to do so without some type class constraint would violate parametricity all over town. Dreadful, just dreadful.
If you don't see why this poses a problem, consider the following type signature:
something :: (a, a) -> b -> a
How would you implement this function? The generic type means it has to be either const . fst or const . snd, right? Hmm.
something (x,y) z = if debugShow z == debugShow y then y else x
> something ('a', 'b') ()
'a'
> something ('a', 'b') 'b'
'b'
Oooooooops! So much for being able to reason about your program in any sane way. That's it, show's over, go home, it was fun while it lasted.
The terrible, no good, unwise answer: Sure, if you don't mind shamelessly cheating. Did I mention that example above was an actual GHCi session? Ha, ha.
import Control.Exception
import Control.Monad
import GHC.Vacuum
debugShow :: a -> String
debugShow = show . nameGraph . vacuumLazy
assertEq :: Eq a => a -> a -> IO ()
assertEq x y = when (x /= y) . throwIO . AssertionFailed $
unlines ["assertEq failed:", '\t':debugShow x, "=/=", '\t':debugShow y]
data NoShow = NoShow1
| NoShow2
deriving (Eq)
> assertEq NoShow1 NoShow2
*** Exception: assertEq failed:
[("|0",["NoShow1|1"]),("NoShow1|1",[])]
=/=
[("|0",["NoShow2|1"]),("NoShow2|1",[])]
Oh. Ok. That looks like a fantastic idea, doesn't it.
Anyway, this doesn't quite give you what you want, since there's no obvious way to fall back to a proper Show instance when available. On the other hand, this lets you do a lot more than show can do, so perhaps it's a wash.
Seriously, though. Don't do this in actual, working code. Ok, error reporting, debugging, logging... that makes sense. But otherwise, it's probably very ill-advised.
I asked this question a while ago on the haskell-cafe list, and the experts said no. Here are some good responses,
http://www.haskell.org/pipermail/haskell-cafe/2011-May/091744.html
http://www.haskell.org/pipermail/haskell-cafe/2011-May/091746.html
The second one mentions GHC advanced overlap, but my experience was that it doesn't really work.
For your particular problem, I'd introduce a typeclass
class MaybeShow a where mshow :: a -> String
make anything that is showable do the logical thing
instance Show a => MaybeShow a where mshow = show
and then, if you have a fixed number of types which wouldn't be showable, say
instance MaybeShow NotShowableA where mshow _ = "<unprintable>"
of course you could abstract it a little,
class NotShowable a
instance NotShowable a => MaybeShow a where mshow _ = "<unprintable>"
instance NotShowable NotShowableA -- etc.
You shouldn't be able to. The simplest way to implement type classes is by having them compile into an extra parameter
foo :: Show s => a -> s
turns into
foo :: show -> a -> s
The program just passess around the type class instances (like v-tables in C++) as ordinary data. This is why you can trivially use things that look not just like multiple dispatch in OO languages, but can dispatch off the return type.
The problem is that a signature
foo :: a -> String
has no way of getting the implementation of Show that goes for a in cases when it has one.
You might be able to get something like this to work in particular implementations, with the correct language extensions (overlapping instance, etc) on, but I havent tried it
class MyShow a where
myShow :: a -> String
instance (Show a) => MyShow a where
myShow = show
instance MyShow a where
myShow = ...
one trick that might help is enable type families. It can let you write code like
instance (a' ~ a, Show a') => MyShow a
which can sometimes help you get code past the compiler that it doesn't think looks okay.

How to get the value of a Maybe in Haskell

I'm relatively new to Haskell and began to read "Real World Haskell".
I Just stumbled over the type Maybe and have a question about how to receive the actual value from a Just 1 for example.
I have written the following code:
combine a b c = (eliminate a, eliminate b, eliminate c)
where eliminate (Just a) = a
eliminate Nothing = 0
This works fine if I use:
combine (Just 1) Nothing (Just 2)
But if I change, for example, 1 to a String it doesn't work.
I think I know why: because eliminate has to give back one type, which is, in this case, an Int. But how can I change eliminate to deal at least with Strings (or maybe with all kind of types)?
From the standard Prelude,
maybe :: b -> (a -> b) -> Maybe a -> b
maybe n _ Nothing = n
maybe _ f (Just x) = f x
Given a default value, and a function, apply the function to the value in the Maybe or return the default value.
Your eliminate could be written maybe 0 id, e.g. apply the identity function, or return 0.
From the standard Data.Maybe,
fromJust :: Maybe a -> a
fromJust Nothing = error "Maybe.fromJust: Nothing"
fromJust (Just x) = x
This is a partial function (does not return a value for every input, as opposed to a total function, which does), but extracts the value when possible.
[edit from Author, 6 years later] This is a needlessly long answer, and I'm not sure why it was accepted. Use maybe or Data.Maybe.fromMaybe as suggested in the highest upvoted answer. What follows is more of a thought experiment rather than practical advice.
So you're trying to create a function that works for a bunch of different types. This is a good time to make a class. If you've programmed in Java or C++, a class in Haskell is kind of like an interface in those languages.
class Nothingish a where
nada :: a
This class defines a value nada, which is supposed to be the class's equivalent of Nothing. Now the fun part: making instances of this class!
instance Nothingish (Maybe a) where
nada = Nothing
For a value of type Maybe a, the Nothing-like value is, well, Nothing! This will be a weird example in a minute. But before then, let's make lists an instance of this class too.
instance Nothingish [a] where
nada = []
An empty list is kind of like Nothing, right? So for a String (which is a list of Char), it will return the empty string, "".
Numbers are also an easy implementation. You've already indicated that 0 obviously represents "Nothingness" for numbers.
instance (Num a) => Nothingish a where
nada = 0
This one will actually not work unless you put a special line at the top of your file
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
Or when you compile it you can set the flags for these language pragmas. Don't worry about them, they're just magic that makes more stuff work.
So now you've got this class and these instances of it...now let's just re-write your function to use them!
eliminate :: (Nothingish a) => Maybe a -> a
eliminate (Just a) = a
eliminate Nothing = nada
Notice I only changed 0 to nada, and the rest is the same. Let's give it a spin!
ghci> eliminate (Just 2)
2
ghci> eliminate (Just "foo")
"foo"
ghci> eliminate (Just (Just 3))
Just 3
ghci> eliminate (Just Nothing)
Nothing
ghci> :t eliminate
eliminate :: (Nothingish t) => Maybe t -> t
ghci> eliminate Nothing
error! blah blah blah...**Ambiguous type variable**
Looks great for values and stuff. Notice the (Just Nothing) turns into Nothing, see? That was a weird example, a Maybe in a Maybe. Anyways...what about eliminate Nothing? Well, the resultant type is ambiguous. It doesn't know what we are expecting. So we have to tell it what type we want.
ghci> eliminate Nothing :: Int
0
Go ahead and try it out for other types; you'll see it gets nada for each one. So now, when you use this function with your combine function, you get this:
ghci> let combine a b c = (eliminate a, eliminate b, eliminate c)
ghci> combine (Just 2) (Just "foo") (Just (Just 3))
(2,"foo",Just 3)
ghci> combine (Just 2) Nothing (Just 4)
error! blah blah Ambiguous Type blah blah
Notice you still have to indicate what type your "Nothing" is, or indicate what return type you expect.
ghci> combine (Just 2) (Nothing :: Maybe Int) (Just 4)
(2,0,4)
ghci> combine (Just 2) Nothing (Just 4) :: (Int, Int, Int)
(2,0,4)
Or, you could restrict the types that your function allows by putting its type signature explicitly in the source. This makes sense if the logical use of the function would be that it is only used with parameters of the same type.
combine :: (Nothingish a) => Maybe a -> Maybe a -> Maybe a -> (a,a,a)
combine a b c = (eliminate a, eliminate b, eliminate c)
Now it only works if all three Maybe things are the same type. That way, it will infer that the Nothing is the same type as the others.
ghci> combine (Just 2) Nothing (Just 4)
(2,0,4)
No ambiguity, yay! But now it is an error to mix and match, like we did before.
ghci> combine (Just 2) (Just "foo") (Just (Just 3))
error! blah blah Couldn't match expected type blah blah
blah blah blah against inferred type blah blah
Well, I think that was a sufficiently long and overblown answer. Enjoy.
I'm new to Haskell too, so I don't know if this exists in the platform yet (I'm sure it does), but how about a "get or else" function to get a value if it exists, else return a default?
getOrElse::Maybe a -> a -> a
getOrElse (Just v) d = v
getOrElse Nothing d = d
This is the answer I was looking for when I came to this question:
https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Maybe.html#v:fromJust
...and similarly, for Either:
https://hackage.haskell.org/package/either-unwrap-1.1/docs/Data-Either-Unwrap.html
They provide functions I would have written myself which unwrap the value from its context.
The eliminate function's type signature is:
eliminate :: Maybe Int -> Int
That's because it returns 0 on Nothing, forcing the compiler to assume that a :: Int in your eliminate function. Hence, the compiler deduces the type signature of the combine function to be:
combine :: Maybe Int -> Maybe Int -> Maybe Int -> (Int, Int, Int)
and that's precisely why it doesn't work when you pass a String to it.
If you wrote it as:
combine a b c = (eliminate a, eliminate b, eliminate c)
where eliminate (Just a) = a
eliminate Nothing = undefined
then it would have worked with String or with any other type. The reason relies on the fact that undefined :: a, which makes eliminate polymorphic and applicable to types other than Int.
Of course, that's not the aim of your code, i.e., to make the combine function total.
Indeed, even if an application of combine to some Nothing arguments would succeed (that's because Haskell is lazy by default), as soon as you try to evaluate the results you would get a runtime error as undefined can't be evaluated to something useful (to put it in simple terms).