What is context in Haskell multiparameter type class - monads

In chapter 15 of Real World Haskell, a type class is defined:
class (Monad m) => MonadSupply s m | m -> s where
A couple paragraphs later, it says that >>= and return don't need to be defined because of the context. But there's no further explanation of what it means by context.
How does the compiler know MonadSupply is an instance of Monad if only 'm' is an instance of Monad?

The "context" is just the part between class and =>, which in this case is the constraint Monad m. And it's not so much that it "knows", more that it enforces it--writing an instance of MonadSupply for a type m that doesn't also have a Monad instance will produce a compiler error.

Related

Explanation why a list with different types is a valid Haskell expression needed

So in an exercise I am given a list like ["xyz", True, 42]. The question was if that is a valid expression in Haskell and what the type of that expression is.
A list can only hold homogenous types but the type of "xyz"is [Char], the type of True is Bool and the type of 42 is Num p => p. That is different types so I can't put them into a list.
That's what I thought. But the given answer to that exercise is "Yes, it is a valid expression. Show-instance!."
Why is it a valid expression although the types of the list elements are different and what is meant with show-instance? I'm thinking of something like superclasses from object oriented languages but I thought this is not how Haskell works.
If we are allowed to define some more context, we can make this a valid expression, for instance with:
import Data.String(IsString(fromString))
instance IsString Bool where
fromString [] = False
fromString _ = True
instance Num Bool where
(+) = (||)
(*) = (&&)
abs = id
signum = id
fromInteger 0 = False
fromInteger _ = True
negate = not
(here I used the truthiness of Python to convert from an Integer and String literal)
Then we can write it with the OverloadedStrings pragma:
{-# LANGUAGE OverloadedStrings #-}
the_list = ["xyz", True, 42]
This will then be equivalent to:
Prelude Data.String> ["xyz", True, 42]
[True,True,True]
But note that the list still contains only Bools, we only made Bool an instance of IsString and Num to enable us to convert string literals and number literals to Bools.
A list of heterogeneous types is not possible in Haskell, and since by default a Bool is not a Num, we thus can not parse that expression without adding some extra magic.
An additional note is that it is valid Haskell grammar: syntactically there is nothing wrong, it is only in the next stage of the compiler: type checking, etc. that it will raise errors, since the syntax is nonsensical.
My lecturer gave me a hint to check for Existential types in Haskell.
I produced a working example from the description from the link above:
{-# LANGUAGE ExistentialQuantification #-}
module Main where
data Showable = forall a . Show a => MkShowable a
pack:: Show a => a -> Showable
pack a= MkShowable a
instance Show Showable where
show (MkShowable a) = show a
hlist :: [Showable]
hlist = [pack "xyz", pack True, pack 42]
main :: IO ()
main = do
putStrLn "Heterogenous list 'camouflaged' as Showable:"
print hlist
This works and produces indeed the input from the exercise. The datatype extension for Existential Quantification in the first line is necessary.
My explanation (I might have gotten something wrong though):
I create a new type Showablewith one constructor MkShowable that takes any value a as long as it is in typeclass Show and thus makes a Showable out of it.
The method pack makes a Show a become a Showable by using the constructor MkShowable I described in 1.
Showable is made an instance of Show-typeclass and tells that if a Showable(MkShowable a) is to be shown, simply show a. So we can easily print our Showables.
Furthermore I created a (heterogenous) list hlist of type [Showable]and packed the values from my example into it, using pack. The list is printed in the main function.
This really reminds me of object-oriented programming.

List Monad: Consequences of the signature of List.flatMap(f: (A) ⇒ GenTraversableOnce[B])

Recently I stumbled upon some code that shouldn't have worked but did. This is a simplified illustration:
val l=List(1,2,3,4,5)
def isEven(i:Int):Option[Int] = if (i%2==0) Some(i) else None
for {elem <- l
even <- isEven(elem)
} yield even
That will produce List(2,4) and might be no surprise to Scala developers.
But it shouldn't work given that List is monadic and should be of this form:
class M[A] {
def flatMap[B](f:A => M[B]):M[B]
def map[B](f:A => B):M[B]
}
Following this definition, every element of a chain of monadic operations must belong to the same monad. Map transforms elements within the context of the monad and flatMap must 'trap' free elements into the monad.
In the example above, we have this desugarized representation:
l.flatMap(elem => isEven(elem))
which is of type: List[Int].flatMap[Int](f:Int => Option[Int]) and does not conform to the monadic definition.
The correct form of isEven should have been:
def isEven(i:Int):List[Int] = if (i%2==0) List(i) else Nil
Looking into the scala-docs, it turns out that the reason that List and Option can be combined in a for comprehension in Scala, is that the flatMap on List is defined as flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): List[B] and that allows for any traversable instance to be 'flatmapped' over. Option is traversable, Set, Seq, and many others are too.
I'm left wondering: What are the consequences of this broader definition of flatMap.
Are there cases that one should be aware/beware of?
The signature you have listed is the notorious "use case", not the method signature, aka the "full signature".
def flatMap[B, That](f: (A) ⇒ GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That
You can build any target for which there is a CanBuildFrom.
The question is quite broad; I'm not sure the list of consequences has been catalogued.
Is the Scala 2.8 collections library a case of "the longest suicide note in history"?
The attempt to do so in the space of one talk.
Or for example:
https://stackoverflow.com/a/17377859/1296806

Why does currying foldr with # produce an operator domain error?

So I'm writing a flatten fn, and I got it to this:
fun flatten ls = List.foldr op # [] ls
And I realized that naming the variable ls should be unnecessary, instead I could probably just paritally apply foldr. But this breaks:
val flatten = List.foldr op # []
Whats making it mess up? I seems like the typ would have to be inferred for both the fun declaration and for the partially applied foldr.
A similar sum function works, which makes me wonder why # is particularly not working:
val sum = List.foldr op + 0
Edit: the error I'm getting:
- val flatten = List.foldr op # [];
stdIn:1.6-2.13 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val flatten = fn : ?.X1 list list -> ?.X1 list
- flatten [[1], [1]];
stdIn:3.1-3.19 Error: operator and operand don't agree [literal]
operator domain: ?.X1 list list
operand: int list list
in expression:
flatten ((1 :: nil) :: (1 :: nil) :: nil)
I'm a bit unclear on what error exactly you are referring to. You mention in the headline that you are getting an "operator domain error", however you code just produces a "value restriction" warning. There is a big difference.
Value restriction is one of the more complex things to get your head around, but in essence it is there to preserve type safety when having references in the language.
The MLton wiki has a great article on value restriction, which covers Why the value restriction exists, unnecessarily rejected programs, alternatives to the value restriction and how to work with the value restriction.
AJ,
Jesper's article both explains the warning you see, and is insightful, but for a more practical solution to your problem, you might want to try this:
val flatten = foldr op # ([]:int list);
I believe that should solve your problem.
EDIT: I chose int list as the explicit type because I observed the nature of your warning message, and inferred from there, int list was what you needed. [=
Note: Above solution destroys polymorphism and restricts input to the type chosen.

What's the difference between `::` and `+:` for prepending to a list)?

List has 2 methods that are specified to prepend an element to an (immutable) list:
+: (implementing Seq.+:), and
:: (defined only in List)
+: technically has a more general type signature—
def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That
def ::[B >: A](x: B): List[B]
—but ignoring the implicit, which according to the doc message merely requires That to be List[B], the signatures are equivalent.
What is the difference between List.+: and List.::? If they are in fact identical, I assume +: would be preferred to avoid depending on the concrete implementation List. But why was another public method defined, and when would client code call it?
Edit
There is also an extractor for :: in pattern matching, but I'm wondering about these particular methods.
See also: Scala list concatenation, ::: vs ++
The best way to determine the difference between both methods is to look it the source code.
The source of :::
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
The source of +::
override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That = bf match {
case _: List.GenericCanBuildFrom[_] => (elem :: this).asInstanceOf[That]
case _ => super.+:(elem)(bf)
}
As you can see, for List, both methods do one and the same (the compiler will choose List.canBuildFrom for the CanBuildFrom argument).
So, which method to use? Normally one would choose the interface (+:) than the implementation (::) but because List is a general data structure in functional languages it has its own methods which are widely used. Many algorithms are build up the way how List works. For example you will find a lot of methods which prepend single elements to List or call the convenient head or tail methods because all these operations are O(1). Therefore, if you work locally with a List (inside of single methods or classes), there is no problem to choose the List-specific methods. But if you want to communicate between classes, i.e. you want to write some interfaces, you should choose the more general Seq interface.
+: is more generic, since it allows the result type to be different from the type of the object it is called on. For example:
scala> Range(1,4).+:(0)
res7: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3)

Adding a Show instance to RWH's RandomState example

I have just typed in the RandomState example from real world haskell. It looks like this:
import System.Random
import Control.Monad.State
type RandomState a = State StdGen a
getRandom :: Random a => RandomState a
getRandom =
get >>= \gen ->
let (val, gen') = random gen in
put gen' >>
return val
getTwoRandoms :: Random a => RandomState (a, a)
getTwoRandoms = liftM2 (,) getRandom getRandom
It works, but the result doesn't get displayed. I get the error message:
No instance for (Show (RandomState (Int, Int)))
arising from a use of `print' at <interactive>:1:0-38
Possible fix:
add an instance declaration for (Show (RandomState (Int, Int)))
In a stmt of a 'do' expression: print it
I am having some trouble adding an instance for Show RandomState. Can anyone show me how this is done?
Thanks.
For the sake of being explicit, as jberryman and the comments on the question imply: Something of type RandomState (a, a) is a function, not a value. To do anything with it, you want to run it with an initial state.
I'm guessing you want something like this:
> fmap (runState getTwoRandoms) getStdGen
((809219598,1361755735),767966517 1872071452)
This is essentially what the runTwoRandoms function a bit further in RWH is doing.
Since RandomState is a synonym for State and there isn't an instance of show defined for State, you won't be able to show it.
You would also not be able to derive show because State is just a wrapper for a function and Haskell has no way to define a show for functions that would be useful:
Prelude> show (+)
<interactive>:1:0:
No instance for (Show (a -> a -> a))
arising from a use of `show' at <interactive>:1:0-7
Possible fix: add an instance declaration for (Show (a -> a -> a))
In the expression: show (+)
In the definition of `it': it = show (+)
EDIT: Forgot to add the other piece: GHCi is giving you that error because it uses show behind the scenes on the expressions you enter... REPL and all that.