This is my first SML program. I am trying to write a function that returns the first number to the nth number of Hofstadter's Female or Male sequence in list form. What I have so far is:
val m = fn (n) => if n = 0 then 1 :: [] else m f (n - 1);
val f = fn (n) => if n = 0 then 0 :: [] else f m (n - 1);
You can learn about the sequence here:
https://en.wikipedia.org/wiki/Hofstadter_sequence#Hofstadter_Female_and_Male_sequences
The error that I am getting is:
[opening sequence.sml]
sequence.sml:1.49 Error: unbound variable or constructor: f
sequence.sml:1.47-1.58 Error: operator is not a function [tycon mismatch]
operator: int list
in expression:
(m <errorvar>) (n - 1)
val it = () : unit
How can I correct this?
I ended up taking this approach:
fun
m (n) = if n = 0 then 0 else n - (f (m (n - 1)))
and
f (n) = if n = 0 then 1 else n - (m (f (n - 1)));
val seq = fn n => List.tabulate((n), f);
It is quite slow. If anybody has a faster version, then I'd love to see it.
Although you have already fixed them, there were two problems with your original approach:
Function application is left-associative in SML so m f (n - 1) was being interpreted as (m f) (n - 1), not the desired m (f (n - 1)). You can fix this by explicitly specifying the bracketing m (f (n - 1)).
To be able to call f from m and m from f, you need to use the keyword fun instead of val on the first declaration (to make the function recursive), and the keyword and instead of fun or val on the second declaration (to make the function mutually recursive with the first function). This would look like
fun f n = ... (* I can call f or m from here! *)
and m n = ... (* I can call f or m from here! *)
To make it faster, you can memoize! The trick is to make f and m take as arguments memoized versions of themselves.
(* Convenience function: Update arr[i] to x, and return x. *)
fun updateAndReturn arr i x = (Array.update (arr, i, SOME x); x)
(*
* Look up result of f i in table; if it's not found, calculate f i and
* store in the table. The token is used so that deeper recursive calls
* to f can also try to store in the table.
*)
fun memo table f token i =
case Array.sub (table, i)
of NONE => updateAndReturn table i (f token i)
| SOME x => x
(*
* Given f, g, and n : int, returns a tuple (f', g') where f' and g' are memoized
* versions of f and g, respectively. f' and g' are defined only on the domain
* [0, n).
*)
fun memoizeMutual (f, g) n =
let
val fTable = Array.array (n, NONE)
val gTable = Array.array (n, NONE)
fun fMemo i = memo fTable f (fMemo, gMemo) i
and gMemo i = memo gTable g (gMemo, fMemo) i
in
(fMemo, gMemo)
end
fun female _ 0 = 1
| female (f, m) n = n - m (f (n - 1))
fun male _ 0 = 0
| male (m, f) n = n - f (m (n - 1))
fun hofstadter upTo =
let
val (male', female') = memoizeMutual (male, female) upTo
in
(List.tabulate (upTo, male'), List.tabulate (upTo, female'))
end
I renamed f and m to female and male. The memoized fMemo and gMemo are threaded through female and male by memoizeMutual. Interestingly, if we call male', then results for both male' and female' are memoized.
To confirm it's indeed faster, try evaluating hofstadter 10000. It's much faster than the forever that your version would take.
As a final note, the only recursive functions are fMemo and gMemo. Every other function I wrote could be written as an anonymous function (val memoizeMutual = fn ..., val female = fn ..., etc.), but I chose not to do so because the syntax for writing recursive functions is much more compact in SML.
To generalize this, you could replace the array version of memoizing with something like a hash table. Then we wouldn't have to specify the size of the memoization up front.
Related
There has to be a minor error in my code because it works in the VSC-Terminal but not in the editor but I do not understand what it could be,
I get the Unbound value Error for the avg_grade and get_grades functions
Let studentlist be a list which safes student records. Each student has a (int*float) grades-list which safes a numeration as a int and the actual grades as floats.
My aim is to calculate the average grade of a single student with the function avg_grade.
I call the single student-record with the age with the get_student function.
type student = {
name : string;
age : int;
grades : (int*float) list;
}
let studentlist =
[ {name="alex"; age=7; grades=[(1,3.)]} ;
{name="bianca"; age=6; grades=[(1, 2.); (2, 3.)]} ]
(* main-function to calculate the average *)
let avg_grade a lst =
try
grades_sum a lst /. length a lst
with
Not_found -> 0.0
(* function to add all the float-grades,
it calls the list with get_grades *)
let grades_sum a lst =
List.fold_left (fun i (_,b) -> i +. b) 0. (get_grades a lst)
(* calls the grades of a single record which is called per age *)
let get_grades a lst =
(get_student a lst).grades
(*calls a single student-record*)
let get_student a lst =
List.find (fun {age;_} -> a = age) lst
(* computes the length of the given grades-list *)
let length a lst =
float_of_int (List.length (get_grades a lst))
You have this:
let avg_grade a lst = try grades_sum a lst /. length a lst with Not_found -> 0.0
But grades_sum isn't defined until after that line of code, so you get:
Error: Unbound value grades_sum
Additionally, a style suggestion. The |> operator may be useful for cleaning up some of your code. For better understanding of how it works:
let (|>) x f = f x
This allows something like f (g (h x)) to be written h x |> g |> f. Doing this lets us see that h x is being evaluated first. The result of that is sent to g, and then finally to f.
Both do the same thing, but the latter may be more expressive of what the code is doing.
You could use this to rewrite:
let length a lst =
float_of_int (List.length (get_grades a lst))
As:
let length a lst =
get_grades a lst |> List.length |> float_of_int
I have some value constraints/properties that I want to check at compile-time. In this example, I want to track whether a vector is normalized or not. I think I have a solution, using type tags, but I need someone with some Elm/FP experience to tell me if I have missed something obvious. Thank you.
module TagExperiment exposing (..)
type Vec t = Vec Float Float Float
type Unit = Unit
type General = General
toGeneral : Vec t -> Vec General
toGeneral (Vec x y z) =
Vec x y z
scaleBy : Vec t -> Vec t -> Vec t
scaleBy (Vec bx by bz) (Vec ax ay az) =
{- Operate on two General's or two Unit's. If you have one of each,
then the Unit needs to be cast to a General.
-}
let
mag =
sqrt ((bx * bx) + (by * by) + (bz * bz))
in
Vec (ax * mag) (ay * mag) (az * mag)
-- These cases work as desired.
a : Vec Unit
a = Vec 0 0 1
b : Vec General
b = Vec 2 2 2
d : Vec Unit
d = scaleBy a a
e : Vec General
e = scaleBy b b
g : Vec General
g = scaleBy (toGeneral a) b
h : Vec General
h = scaleBy b (toGeneral a)
-- Here is where I have trouble.
c : Vec t -- unknown... uh-oh
c = Vec 3 3 3
f : Vec t -- still unknown... sure
f = scaleBy c c
i : Vec Unit -- wrong !!!
i = scaleBy a c
j : Vec Unit -- wrong !!!
j = scaleBy c a
k : Vec General -- lucky
k = scaleBy b c
l : Vec General -- lucky
l = scaleBy c b
{- The trouble is that I am not required to specify a tag for c. I guess the
solution is to write "constructors" and make the built-in Vec constructor
opaque?
-}
newUnitVec : Float -> Float -> Float -> (Vec Unit)
newUnitVec x y z =
-- add normalization
Vec x y z
newVec : Float -> Float -> Float -> (Vec General)
newVec x y z =
Vec x y z
Yes, without Dependant Types the most ergonomic way to ensure constraints on values at compile time is to use opaque types along with a "Parse" approach.
Perhaps something like:
module Vec exposing (UnitVector, Vector, vectorToUnit)
type UnitVector
= UnitVector Float Float Float
type Vector
= Vector Float Float Float
vectorToUnit : Vector -> Maybe UnitVector
vectorToUnit (Vector x y z) =
case ( x, y, z ) of
( 0, 0, 0 ) ->
Nothing
_ ->
normalize x y z
Then, with the only ways to get a UnitVector both defined inside this module and known to obey the constraints, then any time you see a UnitVector at compile-time it is correct to assume the constraints are met.
For vectors in particular, it may be worth having a look at ianmackenzie/elm-geometry for comparison?
In the book Concrete Semantics, exercise 2.11 writes:
Define arithmetic expressions in one variable over integers
(type int) as a data type:
datatype exp = Var | Const int | Add exp exp | Mult exp exp
Define a function eval :: exp ⇒ int ⇒ int such that eval e x evaluates e at the value x. A polynomial can be represented as a list of coefficients, starting with the constant. For example, [4, 2, − 1, 3] represents the polynomial 4+2x−x 2 +3x 3 . Define a function evalp :: int list ⇒ int ⇒ int that evaluates a polynomial at the given value. Define a function coeffs :: exp ⇒ int list that transforms an
expression into a polynomial. This may require auxiliary functions. Prove that coeffs preserves the value of the expression: evalp (coeffs e) x = eval e x. Hint: consider the hint in Exercise 2.10.
As a first try, and because former exercises encouraged to write iterative versions of functions, I wrote the following:
datatype exp = Var | Const int | Add exp exp | Mult exp exp
fun eval :: "exp ⇒ int ⇒ int" where
"eval Var x = x"
| "eval (Const n) _ = n"
| "eval (Add e1 e2) x = (eval e1 x) + (eval e2 x)"
| "eval (Mult e1 e2) x = (eval e1 x) * (eval e2 x)"
fun evalp_it :: "int list ⇒ int ⇒ int ⇒ int ⇒ int" where
"evalp_it [] x xpwr acc = acc"
| "evalp_it (c # cs) x xpwr acc = evalp_it cs x (xpwr*x) (acc + c*xpwr)"
fun evalp :: "int list ⇒ int ⇒ int" where
"evalp coeffs x = evalp_it coeffs x 1 0"
fun add_coeffs :: "int list ⇒ int list ⇒ int list" where
"add_coeffs [] [] = []"
| "add_coeffs (a # as) (b# bs) = (a+b) # (add_coeffs as bs)"
| "add_coeffs as [] = as"
| "add_coeffs [] bs = bs"
(there might be some zip function to do this)
fun mult_coeffs_it :: "int list ⇒ int list ⇒ int list ⇒ int list ⇒ int list" where
"mult_coeffs_it [] bs accs zeros = accs"
| "mult_coeffs_it (a#as) bs accs zeros =
mult_coeffs_it as bs (add_coeffs accs zeros#bs) (0#zeros)"
fun mult_coeffs :: "int list ⇒ int list ⇒ int list" where
"mult_coeffs as bs = mult_coeffs_it as bs [] []"
fun coeffs :: "exp ⇒ int list" where
"coeffs (Var) = [0,1]"
| "coeffs (Const n) = [n]"
| "coeffs (Add e1 e2) = add_coeffs (coeffs e1) (coeffs e2)"
| "coeffs (Mult e1 e2) = mult_coeffs (coeffs e1) (coeffs e2)"
I tried to verify the sought theorem
lemma evalp_coeffs_eval: "evalp (coeffs e) x = eval e x"
but could not. Once I got an advice that writing good definitions is very important in theorem proving, though the adviser did not give details.
So, what is the problem with my definitions, conceptually? Please do not write the good definitions but point out the conceptual problems with my definitions.
UPDATE: upon advice I started to use
fun evalp2 :: "int list ⇒ int ⇒ int" where
"evalp2 [] v = 0"|
"evalp2 (p#ps) v = p + v * (evalp2 ps v) "
and looking into src/HOL/Algebra/Polynomials.thy I formulated
fun add_cffs :: "int list ⇒ int list ⇒ int list" where
"add_cffs as bs =
( if length as ≥ length bs
then map2 (+) as (replicate (length as - length bs) 0) # bs
else add_cffs bs as)"
but that did not help much, simp add: algebra_simps or arith did not solve the corresponding subgoal.
Some hints:
Try running quickcheck and nitpick on the Lemma until no more counter example is found. For the Lemma in your question I get the following counter example:
Quickcheck found a counterexample:
e = Mult Var Var
x = - 2
Evaluated terms:
evalp (coeffs e) x = - 10
eval e x = 4
Try to prove some useful Lemmas about your auxiliary functions first. For example:
lemma "evalp (mult_coeffs A B) x = evalp A x * evalp B x"
Read about calculating with polynomials (e.g. https://en.wikipedia.org/wiki/Polynomial_ring) and choose definitions close to what mathematicians do. Although this one might spoil the fun of coming up with a definition on your own.
Is there a provision in any programming language such that we can write (a==b || a==c) as a==(b||c)?
In other words, is == distributive over logical OR in any programming language? (can we write (a==b || a==c) as a==(b||c)).
There are similar constructs in several languages. IN in SQL, in in python, etc, most evaluating lists or arrays. Closest one I know is Haskell's or which has the type [Bool] -> Bool.
As Anton Gogolev said, it's hard to find a good type for b || c, but not entirely impossible.
You may have to define the higher order function (|||) :: forall a . a -> a -> ((a -> Bool) -> Bool) implemented as a (|||) b = \f -> (f x) || (f y) (here \ means the lambda expression).
Now you can use this (b ||| c) (== 42).
Alternatively you could do :
(|||) :: forall a b . a -> a -> (a -> b -> Bool) -> b -> Bool
(|||) x y f b = (f x b) || (f y b)
and now you can do ( a ||| b ) (==) 42
Of course none of the above will work in languages lacking higher order functions. Moreover, Equality (==) must be function and not language construct. (You can get similar effect with Promises, however).
Maybe the above lines give hints why this approach is not commonly used in the wild. :) a in [b,c] is much simpler to use.
EDIT: (for fun sake)
You can use wrapper type to achieve the goal (in Haskell):
data F a = (Eq a) => Fn (a -> (a->a->Bool) -> Bool) | N a
(===) :: Eq a => F a -> F a -> Bool
(Fn f) === (N n) = f n (==)
(N n) === (Fn f) = f n (==)
(N a) === (N b) = a == b
(Fn a) === (Fn b) = error "not implemented"
(|||) :: Eq a => F a -> F a -> F a
N a ||| N b = Fn $ \c f -> (a `f` c) || (b `f` c)
Fn a ||| N b = Fn $ \c f -> a c f || ( b `f` c )
N a ||| Fn b = Fn $ \c f -> b c f || ( a `f` c )
Fn a ||| Fn b = Fn $ \c f -> (a c f) || (b c f)
Now our new (===) is distributive over (|||). Some efforts has been made to keep associative and commutative properties. Now we can have all of the following:
N 1 === N 2
N 3 === ( N 3 ||| N 8 ||| N 5 )
( N 3 ||| N 8 ||| N 5 ) === N 0
N "bob" === ( N "pete" ||| N "cecil" ||| N "max")
N a === ( N 9 ||| N b ||| N c)
Everything will work smoothly. We could replace standard operators and type N with basic types and write 3 == (3 || 8 || 5). What you ask for is not impossible.
The construct is generic, you can easily extend it with something like (>=) :: F a -> F a -> Bool and now you can use ( 100 || 3 || a || b ) >= c. (Please notice that no lists or arrays are used.)
I'm using ghci and I'm having a problem with a function for getting the factors of a number.
The code I would like to work is:
let factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]
It doesn't complain when I then hit enter, but as soon as I try to use it (with 66 in this case) I get this error message:
Ambiguous type variable 't0' in the constraints:
(Integral t0)
arising from a use of 'factors' at <interactive>:30:1-10
(Num t0) arising from the literal '66' at <interactive>:30:12-13
(RealFrac t0)
arising from a use of 'factors' at <interactive:30:1-10
Probable fix: add a type signature that fixes these type variable(s)
In the expression: factors 66
In the equation for 'it': it = factors 66
The following code works perfectly:
let factorsOfSixtySix = [x | x <- [1..truncate (66/2)], mod 66 x == 0]
I'm new to haskell, and after looking up types and typeclasses, I'm still not sure what I'm meant to do.
Use div for integer division instead:
let factors n = [x | x <- [1.. n `div` 2], mod n x == 0]
The problem in your code is that / requires a RealFrac type for n while mod an Integral one. This is fine during definition, but then you can not choose a type which fits both constraints.
Another option could be to truncate n before using mod, but is more cumbersome. After all, you do not wish to call factors 6.5, do you? ;-)
let factors n = [x | x <- [1..truncate (n/2)], mod (truncate n) x == 0]
If you put a type annotation on this top-level bind (idiomatic Haskell), you get different, possibly more useful error messages.
GHCi> let factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]
GHCi> :t factors
factors :: (Integral t, RealFrac t) => t -> [t]
GHCi> let { factors :: Double -> [Double]; factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]; }
<interactive>:30:64:
No instance for (Integral Double) arising from a use of `truncate'
Possible fix: add an instance declaration for (Integral Double)
In the expression: truncate (n / 2)
In the expression: [1 .. truncate (n / 2)]
In a stmt of a list comprehension: x <- [1 .. truncate (n / 2)]
GHCi> let { factors :: Integer -> [Integer]; factors n = [x | x <- [1..truncate (n/2)], mod n x == 0]; }
<interactive>:31:66:
No instance for (RealFrac Integer) arising from a use of `truncate'
Possible fix: add an instance declaration for (RealFrac Integer)
In the expression: truncate (n / 2)
In the expression: [1 .. truncate (n / 2)]
In a stmt of a list comprehension: x <- [1 .. truncate (n / 2)]
<interactive>:31:77:
No instance for (Fractional Integer) arising from a use of `/'
Possible fix: add an instance declaration for (Fractional Integer)
In the first argument of `truncate', namely `(n / 2)'
In the expression: truncate (n / 2)
In the expression: [1 .. truncate (n / 2)]
I am new to Haskell so please forgive my courage to come up with an answer here but recently i have done this as follows;
factors :: Int -> [Int]
factors n = f' ++ [n `div` x | x <- tail f', x /= exc]
where lim = truncate (sqrt (fromIntegral n))
exc = ceiling (sqrt (fromIntegral n))
f' = [x | x <- [1..lim], n `mod` x == 0]
I believe it's more efficient. You will notice if you do like;
sum (factors 33550336)