I want to use a value defined in the outer scope of a where clause, like so
foo : Nat
foo = case Just 1 of
Nothing => 0
Just x => bar where
bar : Nat
bar = x
but I'm getting
Error: While processing right hand side of foo. While processing right hand side of foo,bar. Undefined name x.
Foo.idr:30:11--30:12
|
30 | bar = x
I don't understand this given what it says in the docs
Any names which are visible in the outer scope are also visible in the where clause (unless they have been redefined, such as xs here). A name which appears in the type will be in scope in the where clause.
Binding x to a new name on the RHS
foo : Nat
foo = case Just 1 of
Nothing => 0
Just x => let x' = x in bar where
bar : Nat
bar = x'
results in a similar error Undefined name x' for bar = x'
You appear to be looking for let not where. Outer scope means arguments to foo.
Related
I have a custom data type in Haskell. I have a custom type from which I later want to get a property and output it. In Java I would just go through the properties with the . (dot) operator, however this doesn't work in Haskell. How would I go about doing this?
This is the code I have now
data Person = P Name Address
type Name = String
type Address = String
x :: Person
x = (P "abc" "def")
y :: Name
y = x.Name
main :: IO ()
main = putStrLn $ "The name is: " ++ y
You can use pattern matching:
y = case x of P name _ -> name
y = name where P name _ = x
y = let P name _ = x in name
You could write a field accessor function:
name (P n _) = n
y = name x
The suggestion in the comments of y = (\(P name _) -> name) x is doing essentially this; the definition of name above is syntax sugar for
name = \(P n _) -> n
which gives the solution from the comment once its definition is inlined.
Or you could redefine your type with record syntax and have the compiler write your accessor:
data Person = P
{ name :: Name
, address :: Address
}
y = name x
Actually, if you do this, I think I'd probably omit the type aliases.
data Person = P
{ name :: String
, address :: String
}
They are just repeating information already available in the field name, and not actually buying you much; for example, the compiler won't prevent you from accidentally reading a name from one person and storing it in the address of another.
I've found block scope {and } in JavaSciprt after ES6 is useful in development, and frequently use for testing small code blocks including the same variable names in different versions side by side.
How do you do in Haskell? What's the best prctice?
If you have some code like this:
foo x y = do
print x
print y
And you want to temporarily test changing the value of x then you can just write:
foo x y = let x = 2 in do
print x
print y
This let syntax creates a new scope and "overwrites" (shadows) any variables with the same name that were previously bound. You can use this let almost everywhere, e.g.:
foo x y = do
let x = 2 in print x
print y
Or even:
foo x y = do
print (let x = 2 in x)
print y
It is really flexible.
There's a few choices, depending on what context you're looking for. I think the thing most likely to be useful to you is that each binding can be associated with a where block, and the variables in each block are independent. So, for example:
foo = component1 * component2 where
component1 = x + y where
x = 32
y = sqrt (magnitude velocity)
component2 = x + y where
x = magnitude acceleration
y = 5.5
In each case, the x and y are in scope only for the component that's currently being defined.
One place that doesn't always work well is in do blocks. There's two reasons for this: first, the associated where block's scope doesn't include any of the variables bound by statements in the do block, and second, because sometimes the thing you want is differing scopes for differing parts of the do block. For those cases, let/in works better. For example:
foo = do
let x = print "hi"
y = putStrLn "hi"
in do
x
y
-- x and y are no longer in scope here
v <- readLn :: IO Int
let x = print [v] -- v is in scope, unlike a where block
y = print v
in do
x
y
Again, in each case, the x and y are in scope for the body of the nested do block, but not in scope in the outer do block. It is also possible to add something to the outer do block's scope, though of course the syntax has to be different (or how would the compiler know which one you wanted?). The difference is that you leave off the in, so:
foo = do
v <- readLn :: IO Int
let w = v + v
print w
First of all, I want to say that I'm very very inexperienced with Haskell, and I know that I have done something (or multiple things) terribly wrong, been struggling for hours but I can't seem to find it.
power :: Int -> Int -> Int
power x y | y == 0 = 1
| x == 0 = 0
list = replicate y x
foldr (*) x list
main = print $ power 3 5
Error most of the time is either x and y not being passed to the replicate function or that foldr is a naked function, I understand what they both mean but have no idea on how I can pass the variables or come up with a solution.
You here created four functions: power, list, foldr and main. But you use variables x and y in the definition of the list function.
You can work with a where clause to specify subexpressions, for example:
power :: Int -> Int -> Int
power x y | y == 0 = 1
| x == 0 = 0
| otherwise = foldr (*) 1 list
where list = replicate y x
or perhaps more elegant with pattern matching:
power :: Int -> Int -> Int
power 0 _ = 0
power x y = foldr (*) 1 (replicate y x)
main = print $ power 3 5
Here we can also eliminate the case for x0, since our foldr starts working with 1, not x.
This algorithm is however not very efficient, since it is linear in the value of y. By checking recursively if the exponent is even or odd, you can make it faster. I leave this as an exercise.
You were very close! The main things that need to be fixed are:
When writing a definition with guards, the “fallback” case needs to be a guard as well, conventionally written with otherwise.
Recall that a definition without guards looks like this, with one left side (a name and parameter patterns/names) and one right side (an expression):
name patterns = expression
With guard conditions, there is one right-hand side for each guard:
name patterns | condition1 = expression1
| condition2 = expression2
…
| otherwise = expressionn
otherwise is really just an alias for True, that is, such a guard always matches. The only thing special about otherwise is that the compiler uses it as a hint when analysing whether a pattern match covers all possible cases.
In order to define a variable list, local to the definition of power, using the parameters x and y, you need to use either a let…in… expression, that is, let block in expression, or a where clause, equation where block. A block is a series of items (in this case, local definitions) which must all be written starting at the same column of indentation, or be delimited by explicit curly braces {…} and semicolons ;.
Using let…in… follows the structure of your original code pretty closely. I will adjust the indentation style to avoid needing to align anything, by putting a newline and a constant amount of indentation instead.
power :: Int -> Int -> Int
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = let
list = replicate y x
in foldr (*) x list
main :: IO ()
main = print $ power 3 5
Attaching a where clause to an equation is slightly more common than using a let…in… expression on the right side of an equation.
power :: Int -> Int -> Int
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = foldr (*) x list
where
list = replicate y x
main :: IO ()
main = print $ power 3 5
Note that in this case, there is a slight difference: the variable list is visible in all of the right-hand sides, although we only use it in one of them. With let list = … in e, list is only defined within e. In general, it’s helpful for readability to keep the scope of a variable as small as possible, although you can certainly go overboard:
a = …
where
b = …
where
c = …
where
d = …
-- If you see this much nesting, rethink!
If you run into issues with alignment and indentation, you can always use explicit delimiters instead. The code I wrote is equivalent to the following.
power :: Int -> Int -> Int; -- Begin ‘power’ signature.
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = let { -- Begin ‘let’ block.
list = replicate y x; -- End ‘list’ equation.
} in foldr (*) x list; -- End ‘let’ block, then end ‘power’ equation.
main :: IO (); -- Begin ‘main’ signature.
main = print $ power 3 5; -- End ‘main’ equation.
Or similarly with where { … }.
This question already has answers here:
Equal (=) Vs left arrow (<-) symbols in haskell
(4 answers)
Closed 6 years ago.
Why can't you use substitution inside a do block?
This code works fine.
test :: (x -> x) -> [x] -> [x]
test f a = map f a
main :: IO ()
main = do
let sq x = x * x :: Int
let ret = test sq [1,2,3]
print ret
But if you remove the let's inside the do block, I got compile errors.
parse error on input ‘=’
Perhaps you need a 'let' in a 'do' block?
e.g. 'let x = 5' instead of 'x = 5'
Is "let x = y" equivalent to "x <- y" inside a do block?
So if the right hand side returns a IO something, you need to use let's (or <-) ?
I know it's a dummy question but I always get compile error with this.
eii
let is how you assign a value to a name inside a do block. let x = y is not equivalent to x <- y. Inside a do block, let desugars like this.
do let x = y
...
becomes
let x = y
in do ...
whereas
do x <- y
...
becomes
do y >>= (\x -> ...)
Bare = is only for top-level assignments, for defining functions and constants (which are a lot like 0-argument functions).
I often hear the phrase, guards are just syntactic sugar for if-then-else (or case statements).
Can somebody please desugar the following instance:
halfOf :: Int -> Int
halfOf x | even x = div x 2
(The function is intentionally partial)
Thanks,
halfOf x =
if even x
then div x 2
else error "Incomplete pattern match"
The exact kind of error triggered by an unhandled case is not specified by the language definition, and varies from compiler to compiler.
edit: If there are multiple guards and/or patterns, each guard or pattern match goes into the non-matching part of the previous case.
compare x y
| x == y = foo
| x /= y = bar
compare _ _ = baz
produces
compare x y =
if x == y
then foo
else if x /= y
then bar
else baz
The semantics of pattern matching are defined in the following section of the standard: Formal Semantics of Pattern Matching.
The step that is relevant to your question is c. As you can see, pattern matches with guards of the form
case v of { p | g1 -> e1 ; ...
| gn -> en where { decls }
_ -> e' }
Are translated to pattern matches without guards as:
case e' of
{y ->
case v of {
p -> let { decls } in
if g1 then e1 ... else if gn then en else y ;
_ -> y }}
So pattern guards are defined in terms of if and "fallthrough" is implemented by binding the expression to a variable and then repeating it once in the else clause of the if and then in the pattern that you'd fall through to.
If there is no case to fall through to (as in your example) one will have been inserted by step b, which inserts a default case _ -> error "No match"