'SML finding the middle of a list
I am new to SML and am trying to create a function middle(lst) of type 'a list -> 'a which returns the middle element of a given list. I want to be able to do this without any pre-implemented functions of the form List.xyz...
I have found a way to do this, but I am using tl, which I believe is part of that pre-implemented list structure.
(* helper for middle *)
fun divvy(first,second) =
if null(tl second) orelse null(tl(tl(second))) then hd first
else divvy(tl first, tl(tl(second)));
(* get middle element in list *)
fun middle([a]) = a
| middle(lst) = divvy(lst,lst);
Is there a way to do this without using pre-implemented functions?
Solution 1:[1]
Use pattern matching for the helper as well.
fun divvy (x::_, [_]) = x
| divvy (x::_, [_,_]) = x
| divvy (_::xs, _::_::ys) = divvy (xs, ys)
Solution 2:[2]
The same program written with pattern-match constructs...
val middle =
fn [] => NONE
| [x] => SOME x
| lst =>
let
fun pick _ [] = NONE
| pick [] _ = NONE
| pick (x::_) [e1] = SOME x
| pick (x::_) [e1, e2] = SOME x
| pick (_::ys) (p::q::rs) = pick ys rs
in
pick lst lst
end;
Run The Snippet Below to see the Results
evalCode();
<pre id="code">
val middle =
fn [] => NONE
| [x] => SOME x
| lst =>
let
fun pick _ [] = NONE
| pick [] _ = NONE
| pick (x::_) [e1] = SOME x
| pick (x::_) [e1, e2] = SOME x
| pick (_::ys) (p::q::rs) = pick ys rs
in
pick lst lst
end;
</pre>
<pre class="sml-input">
middle [];
</pre>
<pre class="sml-input">
middle [1];
</pre>
<pre class="sml-input">
middle [1, 2];
</pre>
<pre class="sml-input">
middle [1, 2, 3];
</pre>
<pre class="sml-input">
middle [1, 2, 3, 4];
</pre>
<pre class="sml-input">
middle [1, 2, 3, 4, 5];
</pre>
<script src="https://unpkg.com/@sosml/interpreter@^1.5.0/build/interpreter.min.js"></script>
<script>
function evalCode() {
try {
let initialState = Interpreter.getFirstState();
const code = document.getElementById('code');
const inputs = document.querySelectorAll(".sml-input");
let interpretationResult = Interpreter.interpret(code.innerText, initialState);
console.log(interpretationResult.state.toString({
stopId: initialState.id + 1
}));
inputs && inputs.length && inputs.forEach(input => {
interpretationResult = Interpreter.interpret(input.innerText, interpretationResult.state);
console.log(interpretationResult.state.toString());
});
} catch (error) {
console.error(error.name, "\n", error.message);
}
}
</script>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | molbdnilo |
| Solution 2 | Chris |
