What is the effect of adding a variable type binding in signature in SML on the Module? - sml

In the following code:
signature DIGIT =
sig
type digit
val make_digit : int -> digit
val increment : digit -> digit
val decrement : digit -> digit
val down_and_up : digit -> digit
val test : digit -> unit
end
structure Digit :> DIGIT =
struct
type digit = int
exception BadDigit
exception FailTest
fun make_digit i = if i < 0 orelse i > 9 then raise BadDigit else i
fun increment d = if d=9 then 0 else d+1
fun decrement d = if d=0 then 9 else d-1
val down_and_up = increment o decrement (* recall o is composition *)
fun test d = if down_and_up d = d then () else raise FailTest
end
I run Digit.test 10; in SML compiler for two different cases, of the line type digit in the aforementioned code:
In case of type digit :
Error: operator and operand don't agree [overload conflict]
operator domain: Digit.digit
operand: [int ty]
In case of type digit = int: uncaught exception FailTest
My question is simply, what difference does it make when we inserted = int so that the output/error is different?

The first one is a type error because you haven't specified what the digit type is in this structure.
The second raises an exception as a runtime error because increment (decrement 10) is 0.
(I would consider it a design problem that you can use any of the functions with any int, not just things that have been validated by make_digit.)

Related

f# concatenate list of objects

type Googol = {
number : float
power : float
result : float
}
let generatePowers (n:float) : list<Googol> =
let rec powerInner (n:float) (p:float) (acc : list<Googol>) =
match n with
| p when p <= 1.0 -> acc
| p when p > 1.0 -> powerInner n (p-1.0) ([{ number=n; power=p; result=n**p}]#acc)
let rec numberInner (n:float) (acc : list<Googol>) =
match n with
| n when n <=1.0 -> acc
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])#acc)
numberInner n []
ProjectEuler.fsx(311,50): error FS0001: This expression was expected to have type
'Googol list'
but here has type
'Googol list -> Googol list'
I am trying to solve this problem -> https://projecteuler.net/problem=56 | but for this I need to generate powers below n < 100. When I try to concatenate [{ number=n; power=p; result=n**p}]#acc
these lists I get the error above. Explain please why error says 'Googol list -> Googol list' is in the function, does I plug a function as a parameter to the function or I plug the actual list when just after concatenation. Is # a function?
This looks like homework or practice, so first I'll give some hints to move on. Finally I'll show a version that seems to work, and then tell how I would approach the problem.
The task is to find the number a ** b, for a and b less than 100, that has the highest sum of its own digits.
The first problem is that float won't give us all the digits of a ** b, so that type is useless to solve the problem. To fix that, we turn to the BigInteger type, and the BigInteger.Pow function. Then we get a 1 followed by 200 zeroes if we run the following snippet, just like it says in the problem description.
let x: bigint = BigInteger.Pow (100I, 100)
let x: string = string x
printfn "s=%s" x
To get useful results, change the Googol type so that it uses bigint, except for power that should be an int.
Why are the functions powerInner and numberInner inside the function generatePowers? This doesn't seem to have a specific purpose, so I suggest moving them out to make this clearer.
The function powerInner do a match on n, but then goes on to name the results p, which shadows the p parameter so that it is unused. Ok, the intention here is probably to match on p rather than n, so just fix that, and then the shadowing of the p parameter is perfectly fine.
The tests first on <= 1 and then on > 1 causes incomplete matches. If the first line checks that the number is less or equal to one, then it must the greater than one in the next line. So just use n -> without the when to fix that. I also suspect you want to test <= 0 instead of 1.
This
[{ number=n; power=p; result=n**p}]#acc
can be just
{ number=n; power=p; result=n**p } :: acc
and here
(powerInner n [])
I suspect you just need a starting value for the power, which would be 99
(powerInner n 99 [])
SPOILER WARNING
After a bit of tinkering, this is what I ended up with, and it seems to print out a useful list of numbers. Note that in order to not run through all 99 by 99 results with printouts, I've used low starting numbers 3 and 5 for the countdowns here, so we get some simple printout we can study for analysis.
type Googol = { number: bigint; power: int; result: bigint }
let rec powerInner (n: bigint) (p: int) (acc: Googol list) =
match p with
| p when p <= 0 -> acc
| p ->
let newNumber = { number = n; power = p; result = n ** p }
printfn "newNumber=%0A" newNumber
powerInner n (p - 1) (newNumber :: acc)
let rec numberInner (n: bigint) (acc: Googol list) =
match n with
| n when n <= 0I -> acc
| n -> numberInner (n - 1I) ((powerInner n 5 []) # acc)
let generatePowers (n: bigint) : Googol list =
numberInner n []
let powers = generatePowers 3I
I'm not sure if this solution is correct. I'd do it differently anyway.
I would simply loop through a and b in two loops, one inside the other. For each a ** b I would convert the result to a string, and then sum the digits of the string. Then I'd simply use a mutable to hold on to whichever result is the highest. The same could be achieved in a more functional way with one of those fancy List functions.
You're missing a parameter here:
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])#acc)
^^^^^^^^^^^^^^^
here
powerInner is defined with three parameters, but you're only passing two.
In F# it is not technically illegal to pass fewer parameters than defined. If you do that, the result will be a function that "expects" the remaining parameters. For example:
let f : int -> int -> string
let x = f 42
// Here, x : int -> string
let y = x 5
// Here, y : string
So in your case omitting the last parameter makes the resulting type Googol list -> Googol list, which then turns out to be incompatible with the type Googol list expected by operator #. Which is what the compiler is telling you in the error message.

Remove Warning this expression should have type unit in Ocaml

Why am I getting Warning this expression should have type unit with this code? although it does what it should do.
let matchInf42 list =
let a = ref 0 in
let lstLength = List.length list in
let rec matchInf4242 list =
match list with
|[]->[]
|m::body->
begin
if (m < 42) then a := !a + 1;
matchInf4242 body
end
in matchInf4242 list;
if(!a = lstLength) then -1 else 0
Warning:
ocamlopt match.ml -o m
File "match.ml", line 14, characters 7-24:
14 | in matchInf4242 list;
^^^^^^^^^^^^^^^^^
Warning 10: this expression should have type unit.
TL;DR: The error you obtain is a typical type error (mostly)
"Mostly" because, admittedly, it is not an "error" but a mere "warning" here, yet it appears this kind of warning (Warning 10: non-unit-statement) is always worth being addressed (i.e., avoided).
It is actually an instance of the following pattern:
42; print_string "…" ;;
(* or more generally *)
any_value_not_having_type_unit; any_value_having_type_unit ;;
(* which would raise *)
> Characters 0-2:
> 42; print_string "…";;
> ^^
> Warning 10: this expression should have type unit.
> …- : unit = ()
Further details
Just to recall, unit is a singleton type (which only has the value ()) and is typically chosen to assign a return type to functions that "return no specific value" but produce some side-effect.
Actually, the sequence operator is "a bit more general / more flexible" as what we might expect:
# let semicolon i j = i; j ;;
val semicolon : 'a -> 'b -> 'b = <fun>
That is to say, it's not semicolon : unit -> 'b -> 'b, and thereby the message we got for the code i; j when i does not have the type unit, is a mere warning, not a type error.
Fixes/workarounds
Two strategies to avoid this warning:
Either ignore it by relying on the ignore function
# ignore;;
- : 'a -> unit = <fun>
# ignore 42; print_string "…";;
…- : unit = ()
Or change/fix the way you compute the left-hand side of the sequence (so its type is unit).
In the particular case of your question example, it would suffice to write this (the only change being indicated with a symbol §):
let matchInf42 list =
let a = ref 0 in
let lstLength = List.length list in
let rec matchInf4242 list =
match list with
|[] -> () (*←§*)
|m::body->
begin
if (m < 42) then a := !a + 1;
matchInf4242 body
end
in matchInf4242 list;
if(!a = lstLength) then -1 else 0
Extra remark
Finally for completeness (even though it was not explicitly part of your question), note that the example function you considered could also be implemented in a more "functional" style (without references nor sequences, avoiding also the need for calling the List.length function beforehand):
let matchInf42 l =
if List.for_all (fun m -> m < 42) l
then -1 else 0
(* or *)
let matchInf42 l =
if List.fold_left (fun r e -> r && e < 42) true l
then -1 else 0
Change
matchInf4242 list
to either
ignore (matchInf4242 list)
or
matchInf4242 list in ().
This makes the statement return () (i.e. a unit), which is what ocaml expects.

getting error when trying to parse integer

Im trying to run an interpreter I made in ocaml and when i to push in a negative value i.e. let e1 = run [PushI -2; PushI 2; LessThan] []. I am getting a syntax error for my parse_int function. I'm trying to write the part of the function that allows for the input of a negative number
type stackVal =
I of int
type command = PushI of int
let rec run (commands : command list) (stack: stackVal list) : stackVal list =
match (commands , stack) with
| (PushI i :: rest, _ ) -> run rest (I i :: stack)
let to_string (s : stackVal) : string =
match s with
| I i -> string_of_int i
let parse_command (s:string) : command =
match take_while is_alpha (String.trim s) with
| ("PushI" , p) -> let Some i = parse_int (String.trim p) in PushI i
let parse_int (s : string) : int option =
match int_of_string s with
| String.get n 0 = '-' -> Some -String.sub n 1 len
| n -> Some n
| exception _ -> None
There is a problem with the pattern-matching of your parse_int function.
match int_of_string s with
| String.get n 0 = '-' -> Some -String.sub n 1 len
| n -> Some n
| exception _ -> None
The first clause here is invalid as "String.get n 0 = '-'" is not an integer constructor. You could write 1 which matches only the integer 1 or _ whitch matches any integer or n which matches any integer and binds it to the name n for the rest of the clause. You can have a look at the manual for more informations.
If you wanted to check if the first char of the string is - pattern matching is not the right tool to do it, simply use an if then else.
However, note that int_of_string works just fine on negative integers, so there is no need to do that part by yourself.
Unrelated, but i noticed that you call the parse_int in the parse_command function. In that case you should define parse_int before parse_command.

Define nested functions in standard ml

I am new in sml. I tried to convert int to int list. For example, assume that there is an input 1234, then output is a list like [1,2,3,4]. And my question is, how can I type nested functions in sml? let in end? There is my code.
fun digit (a : int): int =
let
fun size (a) = if a < 0 then nil
else x = Int.toString x then digit s = size(x)
fun insert (num, nil) = [num]
| insert (num,xs) = x :: insert ()
fun convert (a, s) = if s < 0 then nil
else insert (a / (10*(s - 1)), xs)
then convert(a - (10*(s - 1), s - 1)
in
end
Nested functions are just one way to split up your workload in multiple, smaller parts. Another option is non-nested library functions. The main differences are that functions that aren't nested don't inherit its parent's variable scope, so they can only work with their own input, and functions that are nested aren't available anywhere else and can't be re-used. Let's say you're giving this problem a first stab:
fun digit_meh n = if n < 10 then [n] else n mod 10 :: digit_meh (n div 10)
And you realize it isn't doing exactly as you want:
- digit_meh 1234;
> val it = [4, 3, 2, 1] : int list
You could remove the most significant digit first, but the calculation isn't as trivial as n mod 10, since it depends on the number of digits.
You could generate this list and then reverse it:
fun digit n = rev (digit_meh n)
But the function digit_meh isn't particularly useful outside of this function, so it could be hidden using local-in-end or let-in-end:
local
fun digit_meh n = if n < 10 then [n] else n mod 10 :: digit_meh (n div 10)
in
val digit = rev o digit_meh
end
fun digit n =
let fun meh n = if n < 10 then [n] else n mod 10 :: meh (n div 10)
in rev (meh n) end
Do notice that the function meh's copy of n shadows digit's copy of n.
For clarity you could also name the variables differently.
Or you could look at how rev is doing its thing and do that. It basically treats its input as a stack and puts the top element in a new stack recursively so that the top becomes the bottom, much like StackOverflow's logo would look like if it jumped out and landed upside down like a slinky spring:
fun rev L =
let fun rev_stack [] result = result
| rev_stack (x::xs) result = rev_stack xs (x::result)
in rev_stack L [] end
Because the result is accumulated in an additional argument, and rev should only take a single argument, nesting a function with an extra accumulating argument is a really useful trick.
You can mimic this behavior, too:
fun digit N =
let fun digit_stack n result =
if n < 10
then n::result
else digit_stack (n div 10) (n mod 10::result)
in f N [] end
This way, we continue to treat the least significant digit first, but we put it in the stack result which means it ends up at the bottom / end. So we don't need to call rev and save that iteration of the list.
In practice, you don't have to hide helper functions using either local-in-end or let-in-end; while it can be useful in the case of let-in-end to inherit a parent function's scope, it is not necessary to hide your functions once you start using modules with opaque signatures (the :> operator):
signature DIGIT =
sig
val digit : int -> int list
end
structure Digit :> DIGIT =
struct
fun digit_stack n result =
if n < 10
then n::result
else digit_stack (n div 10) (n mod 10::result)
fun digit n = digit_stack n []
end
As this is entered into a REPL, only the relevant function is available outside of the module:
> structure Digit : {val digit : int -> int list}
signature DIGIT = {val digit : int -> int list}
- Digit.digit 1234;
> val it = [1, 2, 3, 4] : int list
fun aFunctionCallingF2F3 someVariables =
let
<define some functions and local variables here>
fun F2 ...
fun F3 ...
val v1 ...
val v2 ...
in
<Make use of the functions/variables you defined above and `someVariables`>
end
For example,
fun areaCirle r:real =
let fun square x:real = x*x
val pi = 3.14
in
pi * square r
end
Or define functions you need to call beforehand if they are not mutually recursive. If they are mutually recursive, you can look up the keyword and.
fun F2 ...
fun F3 ...
fun aFunctionCallingF2F3 = <make use of F2 F3 directly>
For example,
fun square x:real = x * x
fun areaCircle r = square r * 3.14
Note that you cannot do
fun areaCircle r = square r * 3.14
fun square x:real = x * x
square needs to be defined before areaCircle.

Haskell list comprehension with "x is drawn from a function"

The code below starting with digits returns a List of integers. The code starting with altSumOfDigits should return just the same list, but instead Prelude is complaining about a type error, which i don't understand at this point.
Couldn't match expected type `a' against inferred type `Integer'
digits' :: Integer -> [Integer]
digits' 0 = []
digits' x = (x `mod` 10) : digits' (x `div` 10)
digits :: Integer -> [Integer]
digits 0 = [0]
digits x = reverse $ digits' x
altSumOfDigits :: Integer -> [a]
altSumOfDigits num = [ x | x <- (digits num)]
(I know that altSumOfDigits num = [ x | x <- (digits num)] is rather useless in this form. I'm going to extend its functionality with an if-expression and operations on the single Integers later.)
Any explanations why this doesn't work?
Change (or remove) the type of altSumOfDigits to return a [Integer].
Including the error in the question is good form, and here it is:
Couldn't match type `a' with `Integer'
The type of altSumOfDigits takes a list of Integer, but returns a list of any type a, according to the type you have declared. So it is polymorphic in its return type.
However, you call digits from within altSumOfDigits, which must return a list of Integer only. There is thus no way your altSumOfDigits could return anything other than a list of [Integer].