I'm beginning my first exploration of functional programming with Haskell. I'm struggling a bit with printing a hardcoded value. I created a model representing a car and the gears it can go to. What I want to do is simply print my hardcoded civicNinetyOne when I call printCar. But I keep getting an error when I load the file. I posted the error below, it's an indentation error but from what I've read here at LearnYouAHaskell that call function declaration is correct. Can someone point me to the cause of this issue? Thank you
Error
first_program.hs:10:1: error:
parse error (possibly incorrect indentation or mismatched brackets)
|
10 | printCar:: () -> Car | ^
Code
data Car = Car{
gears :: [String],
currentGear :: String,
brokeGears :: [String],
shiftStroke:: Strokes
}
let civicNinetyOne = Car ["gear1", "gear2", "gear3", "gear4", "gear5"] "gear1" ["gear4"] [("gear1","pull", "gear2"), ("gear2","push", "gear3"), ("gear3","skipShift", "gear5")]
printCar:: () -> Car
printCar = civicNinetyOne
printCar takes an argument like any other function; it's argument type is (), which means there is only one value (also spelled ()) that can be used to call it.
civicNinetyOne, on the other hand, is a value with type Car, not a function of type () -> Car, so cannot itself be assigned to printCar.
The correct definition is
printCar :: () -> Car
printCar () = civicNinetyOne
and it would be called as
> printCar ()
Car {gears = ["gear1","gear2","gear3","gear4","gear5"], currentGear = "gear1", brokeGears = ["gear4"], shiftStroke = [("gear1","pull","gear"),("gear2","push","gear3"),("gear3","skipShift","gear5")]}
For completeness, the let (as pointed out in the comments) is optional in recent versions of GHCi and required in older versions of GHCi, but it is forbidden in a module. (The interactive interpreter behaves somewhat like an implied do block.)
Related
I've seen many OCaml programs that have all their functions at the top and then a unit definition at the end, like:
let rec factorial num =
if num = 0 then 1
else num * factorial (num-1)
let () =
let num2 = read_int () in
print_int (factorial num2)
Why is this? Does it act like a main function? If so, you shouldn't be able to use several of them right?
What is the best way to handle several input for example? Writing several unit definitions?
Yes, a unit expression at the top level of a module acts like the main function of the module. I.e., it gets executed at the time the program is started.
You can have many unit expressions anywhere you can have one unit expression. The ; operator is specifically intended for such cases:
let () =
Printf.printf "hello\n";
Printf.printf "world\n"
As a side comment, I often write a main function in my main module:
let main () =
(* main calculation of program *)
let () = main ()
This is possibly a holdover from all the years I wrote C code.
I have also seen this in other people's code (possibly there are a lot of us who used to write C code).
I really like Jeffrey's answer, but in case if you want extra details and what to know what let () = foo means here is some extracurricular reading.
Abstractly speaking the operation of OCaml programs could be defined as a machine that reduces expressions until they become irreducible. And an irreducible expression is called a value. For example, 5 + 3 is reduced to 8 and there is no other way to reduce 8 so 8 is a value. A more complex example of a value is (fun x -> x + 1). And a more complex example of expression would be
(fun x -> x + 1) 5
Which is reduced to 6.
The whole semantics of the language is defined as a set of such reduction rules. And a program in OCaml is an ordered list of definitions of the form,
let <pattern> = <expression>
So that when an OCaml program is evaluated (executed) it reduces the part of each definition and assigns it to the pattern on the left-hand side, e.g.,
let 5 = 2 + 3
is a valid definition in OCaml. It will reduce the 2 + 3 expression to 5 and then try to match the resulting value with the left-hand side. If it matches, then the next definition is evaluated, and so on. If it doesn't the program is terminated.
Here 5 is a very simple value that matches only with 5 and, in general, your values will be more complex. However, there is a value that is even more primitive than 5. It is a value of type unit that has only one inhabitant, denoted as (). And this is also the value, to which colloquially expressions with side effects are reduced. Since in OCaml every expression must reduce to a value, we need a value that represents no value, and that is unit. For example print_endline "foo" reduces to () with a side effect of emitting string foo to the standard output.
Therefore, when we write
let foo () = print_endline "foo"
let () = foo ()
We evaluate (reduce) the function foo until it reaches the () value that indicates that we fully reduced foo ().
We could also use a wildcard matcher and write
let _ = foo ()
or bind the result to a variable, e.g.,
let bar = foo ()
But it is considered a good style to use () on the left-hand side of an expression that evaluates to () to indicate that the right-hand side doesn't produce any interesting value. It also prevents common errors, e.g.,
let () = foo
will yield an error saying that unit -> unit and can't be matched with unit and even provide a hint: Did you forget to provide ()' as argument?`
As the title states, I see pieces of code online where the variables/functions have ' next to it, what does this do/mean?
ex:
function :: [a] -> [a]
function ...
function' :: ....
The notation comes from mathematics. It is read x prime. In pretty much any math manual you can find something like let x be a number and x' be the projection of ... (math stuff).
Why not using another convention? well, in mathematics It makes a lot of sense because It can be very pedagogical... In programming we aren't used to this convention so I don't see the point of using it, but I am not against it neither.
Just to give you an example of its use in mathematics so you can understand why It is used in Haskell. Below, the same triangle concept but one using prime convention and other not using it. It is pretty clear in the first picture that pairs (A, A'), (B, B'), ... are related by one being the vertex and the prime version being the midpoint of the oposite edge. Whereas in the second example, you just have to remember that A is the midpoint of the oposite edge of vertex P. First is easier and more pedagogical:
As the other answers said, function' is just another variable name. So,
don'tUse :: Int -> IO ()
don'tUse won'tBe''used'' = return ()
is just like
dontUse :: Int -> IO ()
dontUse wontBeUsed = return ()
with slightly different names. The only requirement is that the name starts with a lowercase-letter or underscore, after that you can have as many single-quote characters as you want.
Prelude> let _' = 1
Prelude> let _'' = 2
Prelude> let _''''''''' = 9
Prelude> _' + _'' * _'''''''''
19
...Of course it's not necessarily a good idea to name variables like that; normally such prime-names are used when making a slightly different version of an already named thing. For example, foldl and foldl' are functions with the same signature that do essentially the same thing, only with different strictness (which often affects performance memory usage and whether infinite inputs are allowed, but not the actual results).
That said, to the question
Haskell what does the ' symbol do?
– the ' symbol does in fact do various other things as well, but only when it appears not as a non-leading character in a name.
'a' is a character literal.
'Foo is a constructor used on the type level. See DataKinds.
'bar and ''Baz are quoted names. See TemplateHaskell.
This question already has an answer here:
cis.upenn.edu cis194 Haskell Basics: Functions and Pictures
(1 answer)
Closed 3 years ago.
I encountered the following Haskell code:
trafficController :: Double -> Picture
trafficController t
| round (t/3) `mod` 2 == 0 = trafficLight True
| otherwise = trafficLight False
main :: IO ()
main = animationOf trafficController
I ran and it worked. But how can it be coz the 't' parameter was never applied ?
The t parameter is indeed never applied explicitly. However, you are correct in saying that trafficController needs t to be applied in order to work. What gives?
In this case, the animationOf function is the key. Let’s have a look at its type:
animationOf :: (Double -> Picture) -> IO ()
We can see that animationOf takes a function as its first parameter. Presumably, the implementation of animationOf takes this function, figures out the correct Double to use, applies this value to the function, and then draws the resulting Picture on the screen. (Since this is an animation, it probably does this multiple times.) So even though you never apply the parameter explicitly, animationOf does it for you.
I don't know how to re-assign a variable in a function.
For example,
elephant = 0
function x = elephant = x
Why doesn't this work?
Haskell is a great imperative language, and writing programs that can re-assign state is a really fun advanced topic! This is definitely not the approach you want right now, but come back to it some day 🙂
It takes a bit of effort to define an environment that models global mutable variables. Once you get the hang of it, though, the precision of the types ends up being pretty handy.
We're going to be using the lens and mtl libraries.
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Monad.State
I'll stick with using integers as your question does, but we'll throw in a type alias to remind ourselves that they are being used as the type of the elephant variable.
type Elephant = Integer
You wanted a program whose global mutable state has an elephant. So first let's define what it means to have an elephant. Lens captures this notion nicely.
class HasElephant a
where
elephant :: Lens' a Elephant
Now we can define function, which assigns a new value to elephant.
function :: (MonadState s m, HasElephant s) => Elephant -> m ()
function x =
elephant .= x
The constraints MonadState s m and HasElephant s are saying our program must be able to hold mutable state of some type s, and the type s must have an elephant.
Let's also define a program that prints the elephant.
printElephant :: (MonadState s m, HasElephant s, MonadIO m) => m ()
printElephant =
use elephant >>= (liftIO . print)
This program does I/O (printing), so we have an additional constraint MonadIO m that says our program type m must be able to do I/O.
The elephant variable is probably only one part of some larger program state. Let's define a data type here to represent the entire state (which we'll name Congo just to be cute because the Congo Basin is one place where elephants live).
data Congo = Congo
{ _congoElephant :: Elephant
}
makeLenses ''Congo
(See Control.Lens.TH for a little bit about makeLenses does here using Template Haskell.)
We must define the way in which the Congo has an elephant.
instance HasElephant Congo
where
elephant = congoElephant
Now we can write an example program. Our program will print the value of elephant, then change the value of elephant, then print it again.
main' :: StateT Congo IO ()
main' =
do
printElephant
function 2
printElephant
Then we can run this program.
main :: IO ()
main = Congo 0 & runStateT main' & void
The output is:
0
2
im trying to re-assign an existing variable
You can't do that in Haskell. You can do something close by using IORefs, but this is very rarely the proper solution to a problem - certainly not in situations a beginner might encounter.
Instead you should re-design your program logic, so that it does not require mutable variables to function.
Haskell is a leader in the functional programming world and functional programming is often called "programming without assignment." It's almost the entire point of functional programming to not use assignment. As soon as you've used it, you're not really doing it in a "functional" way any more. Of course there are times for it, but FP tries to minimize those times.
So, to answer your question, "Why doesn't this work?" First of all the syntax is not correct. = does not mean assignment in Haskell. It binds a name to an expression. You cannot do that twice (in the same scope). In other words, "variables" are immutable (like in math). Second, mutation is a side-effecting action and Haskell treats those as impure actions which must be done in the IO world.
I could show you how to actually mutate a reference in Haskell, but I don't think that's what you need at this point.
The most primitive way to bind a variable x to a value v is to write a function taking x as argument, and pass v to that function.
This can sometimes be used to "simulate" the effect of a mutable variable.
E.g., the imperative code
// sum 0..100
i = s = 0;
while (i <= 100) {
s = s+i;
i++;
}
return s;
becomes
final_s = f 0 0 -- the initial values
where
f i s | i <=100 = f (i+1) (s+i) // increment i, augment s
| otherwise = s // return s at the end
The above code is not pretty FP code, but at least it is close enough to imperative code to make it possible to spot the connections.
A final digression:
When one first notices this, it is usually lured to fall into the Blub paradox. One could easily think: "What!? Haskell needs all that stuff to simulate a simple assignment? If in language Blub assignment is trivial, and simulating that in Haskell requires so much effort, then clearly Blub is much better than Haskell!". And this would be a perfect case of the Blub paradox: when a Blub programmer moves to another language, they immediately perceive what can not be directly translated from Blub, and do not notice all the other features of the new language which were not present in Blub.
Their mind now thinks in "Blub", and it requires a great effort to adapt to new models.
Almost as paradoxically, learning both FP and imperative programming is useful precisely because it's non trivial to learn the other paradigm when used to only one of those. If the step between them were narrow, it would not be worth the effort to learn two close approaches to the same problem.
In general this doesn't work because you usually make immutable declarations, rather than specifying a sequence of operations. You can do:
elephant = 3
main = print elephant
But you can also do:
main = print elephant
elephant = 3
Because the code doesn't specify an order of execution, there is no way to interpret multiple assignments as anything other than an error.
If you want to specify a sequence of operations, use do notation:
main = do
let elephant = 0
print elephant
let elephant = 1
print elephant
let elephant = 2
print elephant
The code in a do block is executed in order, so you can effectively reassign variables the way you can in most programming languages.
Note that this code really just creates a new binding for elephant. The old value still exists:
main = do
let elephant = 1
print elephant
let printElephant = print elephant
let elephant = 2
print elephant
printElephant
Because the printElephant function I define is still using the old value of elephant, this prints:
1
2
1
I have an assignment which is to create a calculator program in Haskell. For example, users will be able to use the calculator by command lines like:
>var cola =5; //define a random variable
>cola*2+1;
(print 11)
>var pepsi = 10
>coca > pepsi;
(print false)
>def coke(x,y) = x+y; //define a random function
>coke(cola,pepsi);
(print 15)
//and actually it's more complicated than above
I have no clue how to program this in Haskell. All I can think of right now is to read the command line as a String, parse it into an array of tokens. Maybe go through the array, detect keywords such "var", "def" then call functions var, def which store variables/functions in a List or something like that. But then how do I store data so that I can use them later in my computation?
Also am I on the right track because I am actually very confused what to do next? :(
*In addition, I am not allowed to use Parsec!*
It looks like you have two distinct kinds of input: declarations (creating new variables and functions) and expressions (calculating things).
You should first define some data structures so you can work out what sort of things you are going to be dealing with. Something like:
data Command = Define Definition | Calculate Expression | Quit
type Name = String
data Definition = DefVar Name Expression | DefFunc Name [Name] Expression
-- ^ alternatively, implement variables as zero-argument functions
-- and merge these cases
data Expression = Var Name | Add Expression Expression | -- ... other stuff
type Environment = [Definition]
To start off with, just parse (tokenise and then parse the tokens, perhaps) the stuff into a Command, and then decide what to do with it.
Expressions are comparatively easy. You assume you already have all the definitions you need (an Environment) and then just look up any variables or do additions or whatever.
Definitions are a bit trickier. Once you've decided what new definition to make, you need to add it to the environment. How exactly you do this depends on how exactly you iterate through the lines, but you'll need to pass the new environment back from the interpreter to the thing which fetches the next line and runs the interpreter on it. Something like:
main :: IO ()
main = mainLoop emptyEnv
where
emptyEnv = []
mainLoop :: Environment -> IO ()
mainLoop env = do
str <- getLine
case parseCommnad str of
Nothing -> do
putStrLn "parse failed!"
mainLoop env
Just Quit -> do
return ()
Just (Define d) -> do
mainLoop (d : env)
Just (Calculate e) -> do
putStrLn (calc env e)
mainLoop env
-- the real meat:
parseCommand :: String -> Maybe Command
calc :: Environment -> Expression -> String -- or Integer or some other appropriate type
calc will need to look stuff up in the environment you create as you go along, so you'll probably also need a function for finding which Definition corresponds to a given Name (or complaining that there isn't one).
Some other decisions you should make:
What do I do when someone tries to redefine a variable?
What if I used one of those variables in the definition of a function? Do I evaluate a function definition when it is created or when it is used?
These questions may affect the design of the above program, but I'll leave it up to you to work out how.
First, you can learn a lot from this tutorial for haskell programming
You need to write your function in another doc with .hs
And you can load the file from you compiler and use all the function you create
For example
plus :: Int -> Int -- that mean the function just work with a number of type int and return Int
plus x y = x + y -- they receive x and y and do the operation