Odd reuse in the evaluation of these expressions - haskell

I'm trying to use Debug.Trace.trace to figure out how many times a function is evaluated, and seeing some surprising results.
ghci> import Debug.Trace
ghci> let x = (trace " Eval'd!" (* 2)) 3 in (x, x)
( Eval'd!
6, Eval'd!
6)
ghci> let x = (trace " Eval'd!" (* 2)) 3 in x `seq` (x, x)
Eval'd!
( Eval'd!
6, Eval'd!
6)
ghci> let x = (trace " Eval'd!" (* 2)) (3 :: Int) in (x, x)
( Eval'd!
6,6)
I'm making the assumption that Eval'd is printed once for each evaluation of the (* 2) function. Is that a correct assumption?
Secondly, why is the function ever printed more than once? I suspect that x being of some unspecified type of the Num typeclass has to do with it given that the third case works but I can't think of an explanation.
(x, x) :: Num a => (a, a) guarantees that the two elements of the tuples have the same value just as much as (x, x) :: (Int, Int), so why eval x twice?
UPDATE:
Actually I had assumed that the type of (x, x) was Num a => (a, a). But it's apparently (x, x) :: (Num t, Num t1) => (t, t1).
Why does GHC not realize that t ~ t1 here? I suspect it's related to the answer to my question.

They're not guaranteed to be the same type:
Prelude Debug.Trace> :t let x = (trace " Eval'd!" (* 2)) 3 in (x, x)
let x = (trace " Eval'd!" (* 2)) 3 in (x, x)
:: (Num t, Num t1) => (t, t1)
Also, if you put it in a file, it only gets evaluated once, even when called from GHCi. (This is because in declarations in files but not GHCi, the dreaded monomorphism restriction is on by default):
import Debug.Trace
main = print $ let x = (trace " Eval'd!" (* 2)) 3 in (x, x)
Also,
let x = (trace " Eval'd!" 6) in (x,x)
behaves about the same, so it's really all in the type (class) ambiguity.
The reason why it doesn't share all uses of x is because at GHC core level x, unoptimized, is really a function taking a Num typeclass dictionary argument. To share it, it has to do enough analysis to see that the types are the same.
The reason why it doesn't realize is basically that GHCi is intended for fast code experimentation turnaround, not for creating good code, so it does nearly no optimization at all, so it's almost pure luck whether it detects such things or not.
(There's also an outstanding hole in the GHCi bytecode design that means you cannot enable optimization levels for it, even if you'd want to. Basically it doesn't support "unboxed tuples", which GHC optimization uses a lot.)

Related

Out-of-bounds `select` even though I `constrain` the index

I have a static-length list of values ks :: [SInt16] and an index x :: SInt16. I'd like to index into the list using x:
(.!) :: (Mergeable a) => [a] -> SInt16 -> a
xs .! i = select xs (error "(.!) : out of bounds") i
I would expect to be able to use (.!) with a sufficiently constrained x like this:
sat $ do
let ks = [1, 3, 5, 2, 4]
x <- sInt16 "x"
constrain $ 0 .<= x .&& x .< literal (fromIntegral $ length ks)
let y = ks .! x
return $ y .< x
However, this fails with the error coming from (.!).
Of course, in my real program, I use (.!) all over the place in locations where there is no suitable default value to use in select.
How can I index into a list with a constrained-to-be-in-bounds index?
Simple solution
select is fully expanded by SBV during symbolic execution, hence you do have to provide a proper default value, as you found out. So, if you do want to use select you have to come up with an actual value there.
To address your immediate need, I'd suggest simply defining:
(.!) :: (Mergeable a) => [a] -> SInt16 -> a
[] .! _ = error "(.!): Empty list!"
xs#(x:_) .! i = select xs x i
So long as you make sure you have asserted enough constraints on i, this should work just fine.
A slightly better approach
The above requires your user to keep track of proper constraints on the index variable, and this can get rather hairy. A simple trick to use in these cases is to use a "smart" constructor instead. First define:
import Data.SBV
mkIndex :: SIntegral b => String -> [a] -> Symbolic (SBV b)
mkIndex nm lst = do i <- free nm
constrain $ 0 .<= i .&& i .< literal (fromIntegral (length lst))
pure i
(.!) :: (Mergeable a) => [a] -> SInt16 -> a
[] .! _ = error "(.!): Empty list!"
xs#(x:_) .! i = select xs x i
Now you can say:
p = sat $ do let ks = [1, 3, 5, 2, 4]
x <- mkIndex "x" ks
let y = ks .! x
return $ y .< x
This is just a bit more verbose than your original (as you need to pass the list you want to index into), but it can save a lot of headaches down the road. Furthermore, you can change your mkIndex to put diagnostics, or assert further constraints as needed.
A more defensive approach
The "better" approach above requires you to know in advance the length of the list you'll be indexing into. This is obvious in your example, but I can imagine situations where that information will not be readily available. If that is the case, I'd recommend actually creating a symbolic value for the out-of-bounds access element, and tracking that explicitly yourself. This is more complicated, but you can hide most of it behind a simple data-type. Something like:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.SBV
newtype Index a b = Index (SBV a, SBV b)
mkIndex :: (SymVal a, SymVal b) => String -> Symbolic (Index a b)
mkIndex nm = do def <- free $ nm ++ "_access_out_of_bounds_value"
idx <- free nm
pure $ Index (def, idx)
(.!) :: (SymVal a, SIntegral b) => [SBV a] -> Index a b -> SBV a
xs .! Index (i, i') = select xs i i'
Now assume you try to do a sat, but put in incorrect constraints on your index:
p = sat $ do let ks = [1, 3, 5, 2, 4]
xi#(Index (_, x)) :: Index Int16 Int16 <- mkIndex "x"
-- incorrectly constrain x here to do out-of-bounds
constrain $ x .> 10
let y = ks .! xi
pure $ y .< x
You'll get:
*Main> p
Satisfiable. Model:
x_access_out_of_bounds_value = 0 :: Int16
x = 16386 :: Int16
This way, you can see that something went wrong, and what value the solver picked to satisfy the access-out-of-bounds case.
Summary
Which approach you take really depends on your actual needs. But I'd recommend going for at least the second alternative if possible, as an SMT solver can always "cleverly" pick values to give you unexpected models. You'd have protected yourself against at least the most obvious bugs that way. In a production system, I'd insist on the third approach, as debugging bugs that arise due to complicated constraints can be rather difficult in practice. The more "tracking" variables you leave for yourself, the better.

Expression Evaluation In Haskell: Fixing the type of a sub-expression causes parent expression to be evaluated to different degrees

I am not able to explain the following behavior:
Prelude> let x = 1 + 2
Prelude> let y = (x,x)
Prelude> :sprint y
Prelude> y = _
Now when I specify a type for x:
Prelude> let x = 1 + 2 ::Int
Prelude> let y = (x,x)
Prelude> :sprint y
Prelude> y = (_,_)
Why does the specification of x's type force y to its weak head normal form (WHNF)?
I accidentally discovered this behavior while reading Simon Marlow's Parallel and Concurrent Programming In Haskell.
Here's an informed guess. In your first example,
x :: Num a => a
So
y :: Num a => (a, a)
In GHC core, this y is a function that takes a Num dictionary and gives a pair. If you were to evaluate y, then GHCi would default it for you and apply the Integer dictionary. But from what you've shown, it seems likely that doesn't happen with sprint. Thus you don't yet have a pair; you have a function that produces one.
When you specialize to Int, the dictionary is applied to x, so you get
x :: Int
y :: (Int, Int)
Instead of a function from a dictionary, x is now a thunk. Now no dictionary needs to be applied to evaluate y! y is just the application of the pair constructor to two pointers to the x thunk. Applying a constructor doesn't count as computation, so it's never delayed lazily.

Is it true that order of execution inside a do block doesn't depend on the statement order?

I was reading https://wiki.haskell.org/Do_notation_considered_harmful and was surprised to read the following lines
Newcomers might think that the order of statements determines the order of execution. ... The order of statements is also not the criterion for the evaluation order.
The wiki post gave some examples that demonstrate this property. While the examples make sense, I still don't fully believe that the statement is true, since if I write something like
main = do
putStrLn "foo"
putStrLn "bar"
putStrLn "baz"
The three lines come out in the order of the statements. So what exactly is going on here?
What it says is that the order of statements doesn't influence the evaluation criteria. As #chi points out in IO monad effects are sequenced in order but their evaluation order is still not known. An example of a monad which will make the concept clear:
test = do
x <- Just (2 + undefined)
y <- Nothing
return (x + y)
In ghci:
λ> test
Nothing
The above code has three statements. It can be de-sugared into the following form:
Just (2 + undefined) >>= \x -> Nothing >>= \y -> return (x + y)
Now since (>>=) is left associative, it will be evaluated like this:
(Just (2 + undefined) >>= \x -> Nothing) >>= \y -> return (x + y)
Note that Maybe monad is defined like this:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= _ = Nothing -- A failed computation returns Nothing
(Just x) >>= f = f x -- Applies function f to value x
Applying the value (2 + undefined) to the function \x -> Nothing will result in Nothing.
The expression 2 + undefined is unevaluated, thanks to lazy evaluation strategy followed by Haskell.
Now we have a reduced form:
Nothing >>= \y -> return (2 + undefined + y)
Looking at the Monad instance for it, you can see that this will produce Nothing because Nothing >>= _ = Nothing.
What if the argument was strict instead:
test = do
!x <- Just (2 + undefined)
y <- Nothing
return (y + x)
Demo in ghci:
λ> test
*** Exception: Prelude.undefined
If we follows strict evaluation procedure, then you can see that order actually matters. But in a lazy setting, the order of statements doesn't matter. And hence the wiki claims, "the order of statements is not the criterion for the evaluation order".

Fixed point combinator in Haskell

The fixed point combinator doesn't always produce the right answer given the definition:
fix f = f (fix f)
The following code does not terminate:
fix (\x->x*x) 0
Of course, fix can't always produce the right answer, but I was wondering, can this be improved?
Certainly for the above example, one can implement some fix that looks like
fix f x | f x == f (f x) = f x
| otherwise = fix f (f x)
and gives the correct output.
What is the reason the above definition (or something even better, as this one only handle function with 1 parameter) is not used instead?
Fixed point combinator finds the least-defined fixed point of a function, which is ⊥ in your case (non-termination indeed is undefined value).
You can check, that in your case
(\x -> x * x) ⊥ = ⊥
i.e. ⊥ really is fixed point of \x -> x * x.
As for why is fix defined that way: the main point of fix is to allow you use anonymous recursion and for that you do not need more sophisticated definition.
Your example does not even typecheck:
Prelude> fix (\x->x*x) 0
<interactive>:1:11:
No instance for (Num (a0 -> t0))
arising from a use of `*'
Possible fix: add an instance declaration for (Num (a0 -> t0))
In the expression: x * x
In the first argument of `fix', namely `(\ x -> x * x)'
In the expression: fix (\ x -> x * x) 0
And that gives the clue as to why it doesn't work as you expect. The x in your anonymous function is supposed to be a function, not a number. The reason for this is, as Vitus suggests, that a fixpoint combinator is a way to write recursion without actually writing recursion. The general idea is that a recursive definition like
f x = if x == 0 then 1 else x * f (x-1)
can be written as
f = fix (\f' x -> if x == 0 then 1 else x * f' (x-1))
Your example
fix (\x->x*x) 0
thus corresponds to the expression
let x = x*x in x 0
which makes no sense.
I'm not entirely qualified to talk about what the "fixpoint combinator" is, or what the "least fixed point" is, but it is possible to use a fix-esque technique to approximate certain functions.
Translating Scala by Example section 4.4 to Haskell:
sqrt' :: Double -> Double
sqrt' x = sqrtIter 1.0
where sqrtIter guess | isGoodEnough guess = guess
| otherwise = sqrtIter (improve guess)
improve guess = (guess + x / guess) / 2
isGoodEnough guess = abs (guess * guess - x) < 0.001
This function works by repeatedly "improving" a guess until we determine that it is "good enough". This pattern can be abstracted:
myFix :: (a -> a) -- "improve" the guess
-> (a -> Bool) -- determine if a guess is "good enough"
-> a -- starting guess
-> a
fixApprox improve isGoodEnough startGuess = iter startGuess
where iter guess | isGoodEnough guess = guess
| otherwise = iter (improve guess)
sqrt'' :: Double -> Double
sqrt'' x = myFix improve isGoodEnough 1.0
where improve guess = (guess + x / guess) / 2
isGoodEnough guess = abs (guess * guess - x) < 0.001
See also Scala by Example section 5.3. fixApprox can be used to approximate the fixed point of the improve function passed into it. It repeatedly invokes improve on the input until the output isGoodEnough.
In fact, you can use myFix not only for approximations, but for exact answers as well.
primeAfter :: Int -> Int
primeAfter n = myFix improve isPrime (succ n)
where improve = succ
isPrime x = null [z | z <- [2..pred x], x `rem` z == 0]
This is a pretty dumb way to generate primes, but it illustrates the point. Hm...now I wonder...does something like myFix already exist? Stop...Hoogle time!
Hoogling (a -> a) -> (a -> Bool) -> a -> a, the very first hit is until.
until p f yields the result of applying f until p holds.
Well there you have it. As it turns out, myFix = flip until.
You probably meant iterate:
*Main> take 8 $ iterate (^2) (0.0 ::Float)
[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]
*Main> take 8 $ iterate (^2) (0.001 ::Float)
[1.0e-3,1.0000001e-6,1.0000002e-12,1.0000004e-24,0.0,0.0,0.0,0.0]
*Main> take 8 $ iterate (^2) (0.999 ::Float)
[0.999,0.99800104,0.9960061,0.9920281,0.9841198,0.96849173,0.93797624,0.8797994]
*Main> take 8 $ iterate (^2) (1.0 ::Float)
[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]
*Main> take 8 $ iterate (^2) (1.001 ::Float)
[1.001,1.002001,1.0040061,1.0080284,1.0161213,1.0325024,1.0660613,1.1364866]
Here you have all the execution history explicitly available for your analysis. You can attempt to detect the fixed point with
fixed f from = snd . head
. until ((< 1e-16).abs.uncurry (-).head) tail
$ _S zip tail history
where history = iterate f from
_S f g x = f x (g x)
and then
*Main> fixed (^2) (0.999 :: Float)
0.0
but trying fixed (^2) (1.001 :: Float) will loop indefinitely, so you'd need to develop separate testing for convergence, and even then detection of repellent fixed points like 1.0 will need more elaborate investigation.
You can't define fix the way you've mentioned since f x may not even be comparable. For instance, consider the example below:
myFix f x | f x == f (f x) = f x
| otherwise = myFix f (f x)
addG f a b =
if a == 0 then
b
else
f (a - 1) (b + 1)
add = fix addG -- Works as expected.
-- addM = myFix addG (Compile error)

What does eta reduce mean in the context of HLint

I'm looking at the tutorial http://haskell.org/haskellwiki/How_to_write_a_Haskell_program
import System.Environment
main :: IO ()
main = getArgs >>= print . haqify . head
haqify s = "Haq! " ++ s
When running this program under HLint it gives the following error;
./Haq.hs:11:1: Warning: Eta reduce
Found:
haqify s = "Haq! " ++ s
Why not:
haqify = ("Haq! " ++ )
Can someone shed some light on what exactly "Eta Reduce" means in this context?
Eta reduction is turning \x -> f x into f as long as f doesn't have a free occurence of x.
To check that they're the same, apply them to some value y:
(\x -> f x) y === f' y -- (where f' is obtained from f by substituting all x's by y)
=== f y -- since f has no free occurrences of x
Your definition of haqify is seen as \s -> "Haq! " ++ s, which is syntactic sugar for \s -> (++) "Haq! " s. That, in turn can be eta-reduced to (++) "Haq! ", or equivalently, using section notation for operators, ("Haq! " ++).
Well, eta reduction is (one way) to make point-free functions, and usually means that you can remove the last parameter of a function if it appears at the end on both sides of an expression.
f :: Int -> Int
g :: Int -> Int -> Int
f s = g 3 s
can be converted to
f = g 3
However, in this case it is slightly more complicated, since there is the syntactic sugar of two-parameter operator (++) on the rhs, which is type [a] -> [a] -> [a]. However, you can convert this to a more standard function:
haqify :: [Char] -> [Char]
haqify = (++) "Haq! "
Because (++) is an operator, there are other possibilities:
haqify = ("Haq! " ++ )
That is, the parens convert this into a one-parameter function which applies "Haq!" ++ to its argument.
From lambda calculus, we define eta conversion as the equality:
\x -> M x == M -- if x is not free in M.
See Barendregt, H. P. The Lambda Calculus: Its Syntax and Semantics, 1984.
In the Haskell context, see the definition on the Haskell wiki,
n eta conversion (also written η-conversion) is adding or dropping of abstraction over a function. For example, the following two values are equivalent under η-conversion:
\x -> abs x
and
abs
Converting from the first to the second would constitute an eta reduction, and moving from the second to the first would be an eta abstraction. The term 'eta conversion' can refer to the process in either direction.
Extensive use of η-reduction can lead to Pointfree programming. It is also typically used in certain compile-time optimisations.

Resources