SML programming help tuples - sml

exception No_intersection of string
fun check_in ((m1:real, b1:real), (m2:real, b2:real)):real*real =
The function is supposed to check for an intersection between the two lines. Each pair argument is a slope and a y intercept. I am supposed to find the intersection between the two if it is exists.
I can't make to seem this work for some reason, and have been struggling with this for hours.

Reals are not an equality type in SML, so (m1-m2) = 0 is a type error.
The reason for this is that the limited precision of floating-point representations can give unexpected results due to rounding errors (e.g. (1.0/7.7)*7.7 = 1.0 would return false). You can get around this by using the == operator from the Real library, i.e. Real.==(m1-m2,0) (or just Real.==(m1,m2)). But keep in mind that it can be unreliable.
The second problem is that, according to the return type, your function is supposed to return a value, not print it. All you need to do here is state the return value in the else clause, i.e. just replace print((x,y)) with (x,y).
And for what it's worth, I'd avoid using exceptions if you can; they kind of go against the idea of functional programming. Try returning a (real*real) option instead.

Related

no comparison in if() judgement but seems give a boolean value

if(!word.size()){
return true;
}
whole code screenshot
how here use string.size() lonely to return a boolean value?
I googled the string.size() method although i already know it returns a int value,but here it works like a true/false method;
Lots of things in C++ can be coerced to Booleans. Off the top of my head.
Booleans are trivially convertible to Booleans
Numbers (int or double) can be converted to Boolean; zero is false and anything else is true
Streams (like fstream instances or cout, for instance) can be converted to Boolean and are true if the stream is in "good" condition or false if there's a problem
As indicated in the comments, you shouldn't use this in real code. if (!word.size()) is silly and confusing an should only be seen in code golf challenges. Coding isn't just about making the computer understand what you mean; it's about making sure future readers (including yourself six months down the line) understand as well. And if (word.empty()) conveys the exact same intent to the computer but is much more understandable to the human reader at a glance.
So why does C++ allow this if it's discouraged? Historical reasons, mostly. In the days of C, there was no dedicated bool type. Comparisons returned an integer, and the convention was that 0 meant "false" and anything else (usually 1) meant true. It was the programmer's job to remember which things were Booleans and which were actual integers. C++ came along and (rightly) separated the two, making a special type called bool. But for compatibility with C, they left in the old trick of using integers as Booleans. Successor languages like Java would go on to remove that capability. if (myInteger) is illegal in Java and will give a compiler error.
The language checks if the condition inside the conditional is true or false. In this case, the int value gets converted into a boolean. If the size returns 0 this will get converted to false, any other value will be converted to true.

How to detect list changes without comparing the complete list

I have a function which will fail if there has being any change on the term/list it is using since the generation of this term/list. I would like to avoid to check that each parameter still the same. So I had thought about each time I generate the term/list to perform a CRC or something similar. Before making use of it I would generate again the CRC so I can be 99,9999% sure the term/list still the same.
Going to a specfic answer, I am programming in Erlang, I am thinking on using a function of the following type:
-spec(list_crc32(List :: [term()]) -> CRC32 :: integer()).
I use term, because it is a list of terms, (erlang has already a default fast CRC libraries but for binary values). I have consider to use "erlang:crc32(term_to_binary(Term))", but not sure if there could be a better approach.
What do you think?
Regards, Borja.
Without more context it is a little bit difficult to understand why you would have this problem, particularly since Erlang terms are immutable -- once assigned no other operation can change the value of a variable, not even in the same function.
So if your question is "How do I quickly assert that true = A == A?" then consider this code:
A = generate_list()
% other things in this function happen
A = A.
The above snippet will always assert that A is still A, because it is not possible to change A like you might do in, say, Python.
If your question is "How do I assert that the value of a new list generated exactly the same value as a different known list?" then using either matching or an actual assertion is the fastest way:
start() ->
A = generate_list(),
assert_loop(A).
assert_loop(A) ->
ok = do_stuff(),
A = generate_list(),
assert_loop(A).
The assert_loop/1 function above is forcing an assertion that the output of generate_list/0 is still exactly A. There is no telling what other things in the system might be happening which may have affected the result of that function, but the line A = generate_list() will crash if the list returned is not exactly the same value as A.
In fact, there is no way to change the A in this example, no matter how many times we execute assert_loop/1 above.
Now consider a different style:
compare_loop(A) ->
ok = do_stuff(),
case A =:= generate_list() of
true -> compare_loop(A);
false -> terminate_gracefully()
end.
Here we have given ourselves the option to do something other than crash, but the effect is ultimately the same, as the =:= is not merely a test of equality, it is a match test meaning that the two do not evaluate to the same values, but that they actually match.
Consider:
1> 1 == 1.0.
true
2> 1 =:= 1.0.
false
The fastest way to compare two terms will depend partly on the sizes of the lists involved but especially on whether or not you expect the assertion to pass or fail more often.
If the check is expected to fail more often then the fastest check is to use an assertion with =, an equivalence test with == or a match test with =:= instead of using erlang:phash2/1. Why? Because these tests can return false as soon as a non-matching element is encountered -- and if this non-match occurs near the beginning of the list then a full traverse of both lists is avoided entirely.
If the check is expected to pass more often then something like erlang:phash2/1 will be faster, but only if the lists are long, because only one list will be fully traversed each iteration (the hash of the original list is already stored). It is possible, though, on a short list that a simple comparison will still be faster than computing a hash, storing it, computing another hash, and then comparing the hashes (obviously). So, as always, benchmark.
A phash2 version could look like:
start() ->
A = generate_list(),
Hash = erlang:phash2(A),
assert_loop(Hash).
assert_loop(Hash) ->
ok = do_stuff(),
Hash = erlang:phash2(generate_list()),
loop(Hash).
Again, this is an assertive loop that will crash instead of exit cleanly, so it would need to be adapted to your needs.
The basic mystery still remains, though: in a language with immutable variables why is it that you don't know whether something will have changed? This is almost certainly a symptom of an underlying architectural problem elsewhere in the program -- either that or simply a misunderstanding of immutability in Erlang.

Why would I ever want to use Maybe instead of a List?

Seeing as the Maybe type is isomorphic to the set of null and singleton lists, why would anyone ever want to use the Maybe type when I could just use lists to accomodate absence?
Because if you match a list against the patterns [] and [x] that's not an exhaustive match and you'll get a warning about that, forcing you to either add another case that'll never get called or to ignore the warning.
Matching a Maybe against Nothing and Just x however is exhaustive. So you'll only get a warning if you fail to match one of those cases.
If you choose your types such that they can only represent values that you may actually produce, you can rely on non-exhaustiveness warnings to tell you about bugs in your code where you forget to check for a given a case. If you choose more "permissive" types, you'll always have to think about whether a warning represents an actual bug or just an impossible case.
You should strive to have accurate types. Maybe expresses that there is exactly one value or that there is none. Many imperative languages represent the "none" case by the value null.
If you chose a list instead of Maybe, all your functions would be faced with the possibility that they get a list with more than one member. Probably many of them would only be defined for one value, and would have to fail on a pattern match. By using Maybe, you avoid a class of runtime errors entirely.
Building on existing (and correct) answers, I'll mention a typeclass based answer.
Different types convey different intentions - returning a Maybe a represents a computation with the possiblity of failing while [a] could represent non-determinism (or, in simpler terms, multiple possible return values).
This plays into the fact that different types have different instances for typeclasses - and these instances cater to the underlying essence the type conveys. Take Alternative and its operator (<|>) which represents what it means to combine (or choose) between arguments given.
Maybe a Combining computations that can fail just means taking the first that is not Nothing
[a] Combining two computations that each had multiple return values just means concatenating together all possible values.
Then, depending on which types your functions use, (<|>) would behave differently. Of course, you could argue that you don't need (<|>) or anything like that, but then you are missing out on one of Haskell's main strengths: it's many high-level combinator libraries.
As a general rule, we like our types to be as snug fitting and intuitive as possible. That way, we are not fighting the standard libraries and our code is more readable.
Lisp, Scheme, Python, Ruby, JavaScript, etc., manage to get along with just one type each, which you could represent in Haskell with a big sum type. Every function handling a JavaScript (or whatever) value must be prepared to receive a number, a string, a function, a piece of the document object model, etc., and throw an exception if it gets something unexpected. People who program in typed languages like Haskell prefer to limit the number of unexpected things that can occur. They also like to express ideas using types, making types useful (and machine-checked) documentation. The closer the types come to representing the intended meaning, the more useful they are.
Because there are an infinite number of possible lists, and a finite number of possible values for the Maybe type. It perfectly represents one thing or the absence of something without any other possibility.
Several answers have mentioned exhaustiveness as a factor here. I think it is a factor, but not the biggest one, because there is a way to consistently treat lists as if they were Maybes, which the listToMaybe function illustrates:
listToMaybe :: [a] -> Maybe a
listToMaybe [] = Nothing
listToMaybe (a:_) = Just a
That's an exhaustive pattern match, which rules out any straightforward errors.
The factor I'd highlight as bigger is that by using the type that more precisely models the behavior of your code, you eliminate potential behaviors that would be possible if you used a more general alternative. Say for example you have some context in your code where you uses a type of the form a -> [b], though the only correct alternatives (given your program's specification) are empty or singleton lists. Try as hard as you may to enforce the convention that this context should obey that rule, it's still possible that you'll mess up and:
Somehow a function used in that context will produce a list of two or more items;
And somehow a function that uses the results produced in that context will observe whether the lists have two or more items, and behave incorrectly in that case.
Example: some code that expects there to be no more than one value will blindly print the contents of the list and thus print multiple items when only one was supposed to be.
But if you use Maybe, then there really must be either one value or none, and the compiler enforces this.
Even though isomorphic, e.g. QuickCheck will run slower because of the increase in search space.

Python 2.7: Lesk algorithm returns None

I am creating a program that will disamiguate ambiguos words and I was using nltk. Now, when I came to the stage to use lesk algorithm I am having some trouble.
For example, if I try:
c = lesk('There sign bothered consider inverse logic namely mental illness substance abuse might degree consequence rather cause homelessness ','consider')
c will be None, which means that algorithm will return none.
I tried to give in place of sentence a list of word: i.e:
sent = word_tokenize('There sign bothered consider inverse logic namely mental illness substance abuse might degree consequence rather cause homelessness ')
c = lesk(sent, 'consider')
or even list of lemmatas instead of full words, but it still returns None.
Does anyone know if this is a feature of lesk (when it cannot disambiguate the word to return None), or am I doing something wrong? Also if it is a feature, then can it be removed (to return me a word instead of None)?
Thanks!
Yes, the method returns None if no word sense was found. You may increase the size of the context. As far as I can see in the methods source code the context sentence must be tokenized.

What's the real purpose of `ignore` function in OCaml?

There is an ignore function in OCaml.
val ignore : 'a -> unit
Discard the value of its argument and return (). For instance,
ignore(f x) discards the result of the side-effecting function f. It
is equivalent to f x; (), except that the latter may generate a
compiler warning; writing ignore(f x) instead avoids the warning.
I know what this function will do, but don't get the point of using it.
Anyone can explain or give an example for when we have to use it?
You basically answered your own question. You don't ever have to use it. The point is precisely to avoid the warning. If you write f x; (), the compiler assumes you probably did something wrong. Probably you thought f x returns unit because you rarely want to ignore non-unit values.
However, sometimes that's not true, and you really want to ignore even non-unit values. Writing ignore (f x) documents the fact that you know f x returns something, but you are deliberately ignoring it.
Note that in real code f x might be something more complex, so the chances of you being wrong about the return type of f x are reasonably high. One example is partial application. Consider f : int -> int -> unit. You might accidentally write f 1, forgetting the second argument, and the warning will help you. Another example is if you do open Async, then many functions from the Standard Library change from returning unit to returning unit Deferred.t. Especially when first starting to use Async, it is quite likely that you'll accidentally think the semicolon operator is appropriate in places that you really need to use monadic bind.
As a complement to Ashish Agarwal's answer (because judging from your comment you don't seem very convinced) :
Imagine that I have a function that has side effects, and returns a value indicating something about the computation. Then, if I'm interested in how the computation went, I will need its return value. However, if I don't care about this and simply want the side effects to take place, I would use ignore.
Dumb example : let's say you have a function which sorts an array and returns Was_already_sorted or Was_not_sorted depending on the initial state of the array. Then if for some reason I'm interested in knowing how often my array was sorted, I might need the return value of this function. If not, I will ignore it.
I agree that this is a dumb example. And probably that in many cases there would be better ways to deal with the problem than using ignore (I've just noticed that I never use ignore). If you're really passionate about this, you could try to find examples of use of this function in real-life code (maybe in the source-code of software such as Unison?).
Also, note that you can use let _ = f x to the same end.