Is there a convention so that I know when to expect runX versus getX typeclass functions?
It's purely a matter of how the author preferred to think about what they're representing. And it's often more about the "abstract concept" being represented, not the actual data structure being used to represent it.
If you have some type X and think of an X value as a computation that could be run to get a value, then you'd have a runX function. If you think of it as more like a container, then you'd have a getX function (There are other possible interpretations that could lead to runX or getX or something else, these are just 2 commonly recurring ways of thinking about values).
Of course when we're using first class Haskell values to represent things (and functions are perfectly good values), a lot of the time you could interpret something as either a computation or a container reasonably well. Consider State for representing stateful computations; surely that has to be interpreted as a computation, right? We say runState :: State s a -> s -> (a , s) because we think of it as "running" the State s a, needing an s as additional input. But we could just as easily think of it as "getting" an s -> (a, s) out of the State s a - treating State more like a container.
So the choice between runX and getX isn't really meaningful in any profound tense, but it tells you how the author was thinking about X (and perhaps how they think you should think about it).
Const is so-named in analogy to the function const (which takes an argument to produce the "constant function" that takes another input, ignores it, and returns whatever the first input to const was). But it's thought of as operating at the type level; Const takes a type and generates a "type-level function" that ignores whatever type it is applied to and then is isomorphic to the first type Const was applied to. Isomorphic rather than equal because to create a new type that could have different instances, it needs to have a constructor. At the value level, in order to be an isomorphism you need to be able to get a Const a b from an a (that's the Const constructor), and get the a back out of a Const a b. Since "being isomorphic to a" is all the properties we need it to have there's no real need to think of it as doing anything other than being a simple container of a, so we have getConst.
Identity seems similarly obvious as "just a container" and we have runIdentity. But one of the main motivations for having Identity is to think of Identity a as being a "monadic computation" in the same way that State s a, Reader e a, etc values are. So to continue the analogy we think of Identity as a "do-nothing" computation we run, rather than a simple wrapper container that we get a value out of. It would be perfectly valid to think of Identity as a container (the simplest possible one), but that wasn't the interpretation the authors chose to focus on.
Related
Working through Haskell textbook chapters on different monads, I repeatedly get lost when the authors jump from explaining the details of bind and the monad laws to actually using monads. Suddenly, expressions like "running a function in a monadic context", or "to run a monad" pop up. Similarly, in library documentation and in discussions about monad transformer stacks, I read statements that some function "can be run in any choice of monad". What does this "running inside a monad" exactly mean?
There are two things I don't seem to get straight:
A monad is a type class with functions (return, >>=) and laws. To "run" something inside a monad could thus either mean (a) to provide it as argument to return, or (b) to sequence it using >>=. If the monad is of type m a, then in case a) that something must be of type a, to match the type of the return function. In case b) that something must be a function of type a -> m b, to match the type of the >>= function. From this, I do not understand how I can "run" some function inside an arbitrary monad, because the functions I sequence using >>= must all have the same type signature, and the values I lift using return must be of the specific monad type parameter.
In my understanding, there is no notion of execution or running a computation in a functional language - there is only function application to some argument, and evaluating the function (replacing it with its value). Yet, many specific monads come with a run function such as runReader, runState, etc. These functions are not part of the definition of a monad, and they are plain functions, not in any way special imperative statements outside the functional core of the language. So, what do they "run"?
I feel that having a clear understanding of these concepts is key to understanding monad transformer stacks or similar constructs that seem to be necessary to understand any substantial libraries and any non-trivial programs in Haskell. Thanks very much for helping me to make the leap from simply writing functional code to actually understanding what it means.
Authors who write books and articles often use metaphors and less precise language when they try to explain concepts. The purpose is to give the reader a conceptual intuition for what's going on.
I believe that the concept of 'running' a function falls into this category. Apart from IO, you're right that the functions you use to compose, say, [], Maybe, and so on are no special from other functions.
The notion of running something inside of a monad comes, I think, from the observation that functors are containers. This observation applies to monads as well, since all monads are functors. [Bool] is a container of Boolean values, Maybe Int is a container of (zero or one) numbers. You can even think of the reader functor r -> a as a container of a values, because you can imagine that it's just a very big lookup table.
Being able to 'run a function inside a container' is useful because not all containers enable access to their contents. Again, IO is the prime example, since it's an opaque container.
A frequently asked question is: How to return a pure value from a impure method. Likewise, many beginners ask: How do I get the value of a Maybe? You could even ask: How do I get the value out of a list? Generalised, the question becomes: How to get the value out of the monad.
The answer is that you don't. You 'run the function inside the container', or, as I like to put it, you inject the behaviour into the monad. You never leave the container, but rather let your functions execute within the context of it. Particularly when it comes to IO, this is the only way you can interact with that container, because it's otherwise opaque (I'm here pretending that unsafePerformIO doesn't exist).
Keep in mind when it comes to the bind method (>>=) that while the function 'running inside of it' has the type a -> m b, you can also 'run' a 'normal' function a -> b inside the monad with fmap, because all Monad instances are also Functor instances.
the functions I sequence using >>= must all have the same type signature
This is only sorta true. In some monadic context, we may have the expression
x >>= f >>= g
where
x :: Maybe Int
f :: Int -> Maybe String
g :: String -> Maybe Char
All of these must involve the same monad (Maybe), but note that they do not all have the same type signature. Just as with ordinary function composition, you don't need all the return types to be the same, merely that the input of one function match up with the output of its predecessor.
Here is a simple analogy of "run the function inside the container", with pseudocode:
Let's say you have some type Future[String] which represents a container that will have a string "at some time in the future":
val tweet: Future[String] = getTweet()
Now you want to access the string -- but you do not take the string out of the context -- the "future" -- you simply use the string "inside the container":
tweet.map { str =>
println(str)
}
Inside these curly braces, you are "in the future". For example:
val tweet: Future[String] = getTweet()
tweet.map { str =>
println(str)
}
println("Length of tweet string is " + tweet.length) // <== WRONG -- you are not yet in the future
The tweet.length is trying to access the tweet outside of the container. So "being inside the container" is analogous to, when reading the source code, "being inside the curly braces of a map (flatmap, etc.)". You are dipping inside of the container.
tweet.map { str =>
println("Length of tweet string is " + str.length) // <== RIGHT
}
Albeit a very simple analogy, I find this useful when thinking of all monads in general. In the source code, where is one "inside the container" and where is one outside? In this case, the length function is running in the future, or "inside the container".
My question came up while following the tutorial Functors, Applicatives, And Monads In Pictures and its JavaScript version.
When the text says that functor unwraps value from the context, I understand that a Just 5 -> 5 transformation is happening. As per What does the "Just" syntax mean in Haskell? , Just is "defined in scope" of the Maybe monad.
My question is what is so magical about the whole unwrapping thing? I mean, what is the problem of having some language rule which automatically unwraps the "scoped" variables? It looks to me that this action is merely a lookup in some kind of a table where the symbol Just 5 corresponds to the integer 5.
My question is inspired by the JavaScript version, where Just 5 is prototype array instance. So unwrapping is, indeed, not rocket science at all.
Is this a "for-computation" type of reason or a "for-programmer" one? Why do we distinguish Just 5 from 5 on the programming language level?
First of all, I don't think you can understand Monads and the like without understanding a Haskell like type system (i.e. without learning a language like Haskell). Yes, there are many tutorials that claim otherwise, but I've read a lot of them before learning Haskell and I didn't get it. So my advice: If you want to understand Monads learn at least some Haskell.
To your question "Why do we distinguish Just 5 from 5 on the programming language level?". For type safety. In most languages that happen not to be Haskell null, nil, whatever, is often used to represent the absence of a value. This however often results in things like NullPointerExceptions, because you didn't anticipate that a value may not be there.
In Haskell there is no null. So if you have a value of type Int, or anything else, that value can not be null. You are guarantied that there is a value. Great! But sometimes you actually want/need to encode the absence of a value. In Haskell we use Maybe for that. So something of type Maybe Int can either be something like Just 5 or Nothing. This way it is explicit that the value may not be there and you can not accidentally forget that it might be Nothing because you have to explicitly unwrap the value.
This has nothing really to do with Monads, except that Maybe happens to implement the Monad type class (a type class is a bit like a Java interface, if you are familiar with Java). That is Maybe is not primarily a Monad, but just happens to also be a Monad.
I think you're looking at this from the wrong direction. Monad is explicitly not about unwrapping. Monad is about composition.
It lets you combine (not necessarily apply) a function of type a -> m b with a value of type m a to get a value of type m b. I can understand where you might think the obvious way to do that is unwrapping the value of type m a into an value of type a. But very few Monad instances work that way. In fact, the only ones that can work that way are the ones that are equivalent to the Identity type. For nearly all instances of Monad, it's just not possible to unwrap a value.
Consider Maybe. Unwrapping a value of type Maybe a into a value of type a is impossible when the starting value is Nothing. Monadic composition has to do something more interesting than just unwrapping.
Consider []. Unwrapping a value of type [a] into a value of type a is impossible unless the input just happens to be a list of length 1. In every other case, monadic composition is doing something more interesting than unwrapping.
Consider IO. A value like getLine :: IO String doesn't contain a String value. It's plain impossible to unwrap, because it isn't wrapping something. Monadic composition of IO values doesn't unwrap anything. It combines IO values into more complex IO values.
I think it's worthwhile to adjust your perspective on what Monad means. If it were only an unwrapping interface, it would be pretty useless. It's more subtle, though. It's a composition interface.
A possible example is this: consider the Haskell type Maybe (Maybe Int). Its values can be of the following form
Nothing
Just Nothing
Just (Just n) for some integer n
Without the Just wrapper we couldn't distinguish between the first two.
Indeed, the whole point of the optional type Maybe a is to add a new value (Nothing) to an existing type a. To ensure such Nothing is indeed a fresh value, we wrap the other values inside Just.
It also helps during type inference. When we see the function call f 'a' we can see that f is called at the type Char, and not at type Maybe Char or Maybe (Maybe Char). The typeclass system would allow f to have a different implementation in each of these cases (this is similar to "overloading" in some OOP languages).
My question is, what is so magical about the whole unwrapping thing?
There is nothing magical about it. You can use garden-variety pattern matching (here in the shape of a case expression) to define...
mapMaybe :: (a -> b) -> Maybe a -> Maybe b
mapMaybe f mx = case mx of
Just x -> Just (f x)
_ -> mx
... which is exactly the same than fmap for Maybe. The only thing the Functor class adds -- and it is a very useful thing, make no mistake -- is an extra level of abstraction that covers various structures that can be mapped over.
Why do we distinguish Just 5 from 5 on programming language level?
More meaningful than the distinction between Just 5 and 5 is the one between their types -- e.g. between Maybe Intand Int. If you have x :: Int, you can be certain x is an Int value you can work with. If you have mx :: Maybe Int, however, you have no such certainty, as the Int might be missing (i.e. mx might be Nothing), and the type system forces you to acknowledge and deal with this possibility.
See also: jpath's answer for further comments on the usefulness of Maybe (which isn't necessarily tied to classes such as Functor and Monad); Carl's answer for further comments on the usefulness of classes like Functor and Monad (beyond the Maybe example).
What "unwrap" means depends on the container. Maybe is just one example. "Unwrapping" means something completely different when the container is [] instead of Maybe.
The magical about the whole unwrapping thing is the abstraction: In a Monad we have a notion of "unwrapping" which abstracts the nature of the container; and then it starts to get "magical"...
You ask what Just means: Just is nothing but a Datatype constructor in Haskell defined via a data declaration like :
data Maybe a = Just a | Nothing
Just take a value of type a and creates a value of type Maybe a. It's Haskell's way to distinguigh values of type a from values of type Maybe a
First of all, you need to remove monads from your question. They have nothing to do this. Treat this articles as one of the points of view on the monads, maybe it does not suit you, you may still little understood in the type system that would understand monads in haskell.
And so, your question can be rephrased as: Why is there no implicit conversion Just 5 => 5? But answer is very simple. Because value Just 5 has type Maybe Integer, so this value may would be Nothing, but what must do compiler in this case? Only programmer can resolve this situation.
But there is more uncomfortable question. There are types, for example, newtype Identity a = Identity a. It's just wrapper around some value. So, why is there no impliciti conversion Identity a => a?
The simple answer is - an attempt to realize this would lead to a different system types, which would not have had many fine qualities that exist in the current. According to this, it can be sacrificed for the benefit of other possibilities.
Functions aren't instances of the Show typeclass, so one cannot see it in neat form. But compiler has it somewhere on which it returns fails.
So why it is not possible to show it and if it can be what it will look like?
I shall be thankful if you could take some trivial example to state this.
Haskell is a compiled language. Functions are, internally, just code. It doesn't really make sense to Show them. Even if it was possible, it'd probably not be desirable, because it would most likely mean that extensionally equal functions have different String representations, and/or that compiler optimisations would be visible in the String that is being generated.
The only things you can do are: define a dummy representation for all functions, or define a specific instance for specific function types with small domains (say, functions of type Bool -> Bool or Bool -> Int) that can still easily be observed completely from the outside.
There is no way to inspect functions to obtain their code and any captured environment (in the case of a thunk).
In order to show a function one would typically try to create an instance of Show:
instance Show (a -> b) where
show f =
What value goes on the right hand side of the =? As I said, you can't inspect functions so the common solution is to use:
show f = "<function>"
Which is what is implemented in Text.Show.Functions
I have scoured the internet for an actual explanation of what this keyword does. Every Haskell tutorial that I have looked at just starts using it randomly and never explains what it does (and I've looked at many).
Here's a basic piece of code from Real World Haskell that uses Just. I understand what the code does, but I don't understand what the purpose or function of Just is.
lend amount balance = let reserve = 100
newBalance = balance - amount
in if balance < reserve
then Nothing
else Just newBalance
From what I have observed, it is related to Maybe typing, but that's pretty much all I have managed to learn.
A good explanation of what Just means would be very much appreciated.
It's actually just a normal data constructor that happens to be defined in the Prelude, which is the standard library that is imported automatically into every module.
What Maybe is, Structurally
The definition looks something like this:
data Maybe a = Just a
| Nothing
That declaration defines a type, Maybe a, which is parameterized by a type variable a, which just means that you can use it with any type in place of a.
Constructing and Destructing
The type has two constructors, Just a and Nothing. When a type has multiple constructors, it means that a value of the type must have been constructed with just one of the possible constructors. For this type, a value was either constructed via Just or Nothing, there are no other (non-error) possibilities.
Since Nothing has no parameter type, when it's used as a constructor it names a constant value that is a member of type Maybe a for all types a. But the Just constructor does have a type parameter, which means that when used as a constructor it acts like a function from type a to Maybe a, i.e. it has the type a -> Maybe a
So, the constructors of a type build a value of that type; the other side of things is when you would like to use that value, and that is where pattern matching comes in to play. Unlike functions, constructors can be used in pattern binding expressions, and this is the way in which you can do case analysis of values that belong to types with more than one constructor.
In order to use a Maybe a value in a pattern match, you need to provide a pattern for each constructor, like so:
case maybeVal of
Nothing -> "There is nothing!"
Just val -> "There is a value, and it is " ++ (show val)
In that case expression, the first pattern would match if the value was Nothing, and the second would match if the value was constructed with Just. If the second one matches, it also binds the name val to the parameter that was passed to the Just constructor when the value you're matching against was constructed.
What Maybe Means
Maybe you were already familiar with how this worked; there's not really any magic to Maybe values, it's just a normal Haskell Algebraic Data Type (ADT). But it's used quite a bit because it effectively "lifts" or extends a type, such as Integer from your example, into a new context in which it has an extra value (Nothing) that represents a lack of value! The type system then requires that you check for that extra value before it will let you get at the Integer that might be there. This prevents a remarkable number of bugs.
Many languages today handle this sort of "no-value" value via NULL references. Tony Hoare, an eminent computer scientist (he invented Quicksort and is a Turing Award winner), owns up to this as his "billion dollar mistake". The Maybe type is not the only way to fix this, but it has proven to be an effective way to do it.
Maybe as a Functor
The idea of transforming one type to another one such that operations on the old type can also be transformed to work on the new type is the concept behind the Haskell type class called Functor, which Maybe a has a useful instance of.
Functor provides a method called fmap, which maps functions that range over values from the base type (such as Integer) to functions that range over values from the lifted type (such as Maybe Integer). A function transformed with fmap to work on a Maybe value works like this:
case maybeVal of
Nothing -> Nothing -- there is nothing, so just return Nothing
Just val -> Just (f val) -- there is a value, so apply the function to it
So if you have a Maybe Integer value m_x and an Int -> Int function f, you can do fmap f m_x to apply the function f directly to the Maybe Integer without worrying if it's actually got a value or not. In fact, you could apply a whole chain of lifted Integer -> Integer functions to Maybe Integer values and only have to worry about explicitly checking for Nothing once when you're finished.
Maybe as a Monad
I'm not sure how familiar you are with the concept of a Monad yet, but you have at least used IO a before, and the type signature IO a looks remarkably similar to Maybe a. Although IO is special in that it doesn't expose its constructors to you and can thus only be "run" by the Haskell runtime system, it's still also a Functor in addition to being a Monad. In fact, there's an important sense in which a Monad is just a special kind of Functor with some extra features, but this isn't the place to get into that.
Anyway, Monads like IO map types to new types that represent "computations that result in values" and you can lift functions into Monad types via a very fmap-like function called liftM that turns a regular function into a "computation that results in the value obtained by evaluating the function."
You have probably guessed (if you have read this far) that Maybe is also a Monad. It represents "computations that could fail to return a value". Just like with the fmap example, this lets you do a whole bunch of computations without having to explicitly check for errors after each step. And in fact, the way the Monad instance is constructed, a computation on Maybe values stops as soon as a Nothing is encountered, so it's kind of like an immediate abort or a valueless return in the middle of a computation.
You Could Have Written Maybe
Like I said before, there is nothing inherent to the Maybe type that is baked into the language syntax or runtime system. If Haskell didn't provide it by default, you could provide all of its functionality yourself! In fact, you could write it again yourself anyway, with different names, and get the same functionality.
Hopefully you understand the Maybe type and its constructors now, but if there is still anything unclear, let me know!
Most of the current answers are highly technical explanations of how Just and friends work; I thought I might try my hand at explaining what it's for.
A lot of languages have a value like null that can be used instead of a real value, at least for some types. This has made a lot of people very angry and been widely regarded as a bad move. Still, it's sometimes useful to have a value like null to indicate the absence of a thing.
Haskell solves this problem by making you explicitly mark places where you can have a Nothing (its version of a null). Basically, if your function would normally return the type Foo, it instead should return the type Maybe Foo. If you want to indicate that there's no value, return Nothing. If you want to return a value bar, you should instead return Just bar.
So basically, if you can't have Nothing, you don't need Just. If you can have Nothing, you do need Just.
There's nothing magical about Maybe; it's built on the Haskell type system. That means you can use all the usual Haskell pattern matching tricks with it.
Given a type t, a value of Just t is an existing value of type t, where Nothing represents a failure to reach a value, or a case where having a value would be meaningless.
In your example, having a negative balance doesn't make sense, and so if such a thing would occur, it is replaced by Nothing.
For another example, this could be used in division, defining a division function that takes a and b, and returns Just a/b if b is nonzero, and Nothing otherwise. It's often used like this, as a convenient alternative to exceptions, or like your earlier example, to replace values that don't make sense.
A total function a->b can find a value of type b for every possible value of type a.
In Haskell not all functions are total. In this particular case function lend is not total - it is not defined for case when balance is less than reserve (although, to my taste it would make more sense to not permit newBalance to be less than reserve - as is, you can borrow 101 from a balance of 100).
Other designs that deal with non-total functions:
throw exceptions upon checking input value does not fit the range
return a special value (primitive type): favourite choice is a negative value for integer functions that are meant to return Natural numbers (for example, String.indexOf - when a substring is not found, the returned index is commonly designed to be negative)
return a special value (pointer): NULL or some such
silently return without doing anything: for example, lend could be written to return old balance, if the condition for lending is not met
return a special value: Nothing (or Left wrapping some error description object)
These are necessary design limitations in languages that cannot enforce totality of functions (for example, Agda can, but that leads to other complications, like becoming turing-incomplete).
The problem with returning a special value or throwing exceptions is that it is easy for the caller to omit handling of such a possibility by mistake.
The problem with silently discarding a failure is also obvious - you are limiting what the caller can do with the function. For example, if lend returned old balance, the caller has no way of knowing if balance has changed. It may or may not be a problem, depending on the intended purpose.
Haskell's solution forces the caller of a partial function to deal with the type like Maybe a, or Either error a because of the function's return type.
This way lend as it is defined, is a function that doesn't always compute new balance - for some circumstances new balance is not defined. We signal this circumstance to the caller by either returning the special value Nothing, or by wrapping the new balance in Just. The caller now has freedom to choose: either handle the failure to lend in a special way, or ignore and use old balance - for example, maybe oldBalance id $ lend amount oldBalance.
Function if (cond :: Bool) then (ifTrue :: a) else (ifFalse :: a) must have the same type of ifTrue and ifFalse.
So, when we write then Nothing, we must use Maybe a type in else f
if balance < reserve
then (Nothing :: Maybe nb) -- same type
else (Just newBalance :: Maybe nb) -- same type
I have a list of values (or functions) of any type. I have another list of functions of any type. The user at runtime will choose one from the first list, and another from the second list. I have a mechanism to ensure that the two items are type compatible (value or output from first is compatible with input of second).
I need some way to call the function with the value (or compose the functions). If the second function has concrete types, unsafeCoerce works fine. But if it's of the form:
polyFunc :: MyTypeclass a => a -> IO ()
polyFunc x = print . show . typeclassFunc x
Then unsafeCoerce doesn't work since it can't resolve to a concrete type.
Is there any way to do what I'm trying to do?
Here's an example of what the lists might look like. However... I'm not limited to this, if there is some other way to represent these that will solve the problem, I would like to know. A critical thing to consider is that: the list can change at runtime so I do not know at compile time all the possible types that might be involved.
data Wrapper = forall a. Wrapper a
firstList :: [Wrapper]
firstList = [Wrapper "blue", Wrapper 5, Wrapper valueOfMyTypeclass]
data OtherWrapper = forall a. Wrapper (a -> IO ())
secondList :: [OtherWrapper]
secondList = [OtherWrapper print, OtherWrapper polyFunc]
Note: As for why I want to do such a crazy thing:
I'm generating code and typechecking it with hint. But that happens at runtime. The problem is that hint is slow at actually executing things and high performance for this is critical. Also, at least in certain cases, I do not want to generate code and run it through ghc at runtime (though we have done some of that, too). So... I'm trying to find somewhere in the middle: dynamically hook things together without having to generate code and compile, but run it at compiled speed instead of interpreted.
Edit: Okay, so now that I see what's going on a bit more, here's a very general approach -- don't use polymorphic functions directly at all! Instead, use functions of type Dynamic -> IO ()! Then, they can use "typecase"-style dispatch directly to choose which monomorphic function to invoke -- i.e. just switching on the TypeRep. You do have to encode this dispatch directly for each polymorphic function you're wrapping. However, you can automate this with some template Haskell if it becomes enough of a hassle.
Essentially, rather than overloading Haskell's polymorphism, just as Dynamic embeds an dynamically typed language in a statically typed language, you now extend that to embed dynamic polymorphism in a statically typed language.
--
Old answer: More code would be helpful. But, as far as I can tell, this is the read/show problem. I.e. You have a function that produces a polymorphic result, and a function that takes a polymorphic input. The issue is that you need to pick what the intermediate value is, such that it satisfies both constraints. If you have a mechanism to do so, then the usual tricks will work, making sure you satisfy that open question which the compiler can't know the answer to.
I'm not sure that I completely understand your question. But since you have value and function which have compatible types you could combine them into single value. Then compiler could prove that types do match.
{-# LANGUAGE ExistentialQuantification #-}
data Vault = forall a . Vault (a -> IO ()) a
runVault :: Vault -> IO ()
runVault (Vault f x) = f xrun