Related
I'm restricting myself the use of prebuilt-in functions for training purposes. I have recoded length as count and it works.
I have a search funtion that simply returns a value at index in a list when given an index and a list. It works completly fine. It throws an error when the index is too large.
search [] _ = error "index too large"
search (a:_) 0 = a
search (_:a) b = search a (b - 1)
Now, I want a safeSearch function that return Nothing if the index is too large of if the list is empty. So I've simply done this.
safeSearch :: [a] -> Int -> Maybe a
safeSearch a b
| b < 0 || b >= count a = Nothing
| otherwise = Just (search a b)
And it works! ... as long as you don't try it on an empty list. Even with an index too large for the list length.
main = print(safeSearch [] 5)
This crashes and I really can't find any way around it.
Even though I don't think my second line is usefull (because if the list is empty, its count is 0 so we drop in the first guard and it should return Nothing?) its not working. Removing it does not solve the problem.
Here's the compile-time error.
main.hs:91:8: error:
* Ambiguous type variable `a0' arising from a use of `print'
prevents the constraint `(Show a0)' from being solved.
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance Show Ordering -- Defined in `GHC.Show'
instance Show Integer -- Defined in `GHC.Show'
instance Show a => Show (Maybe a) -- Defined in `GHC.Show'
...plus 22 others
...plus 13 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In the expression: print (safeSearch [] 5)
In an equation for `main': main = print (safeSearch [] 5)
|
91 | main = print(safeSearch [] 5)
| ^^^^^^^^^^^^^^^^^^^^^^
exit status 1
Any idea? Something I'm missing or even completly going wrong? A concept I need to understand deeper?
The problem is a compile error. That means it isn't actually running your code and hitting your error "index too large" call; the compiler is rejecting your code before it can even try to run it. So you're looking in the wrong place if you're trying to change the code to avoid that.
What's actually happening is that safeSearch [] 5 is returning a value of type Maybe a, where a is the type of the elements in the list. But you didn't include any elements in the list, so there is nothing at all to decide what that type a is.
Your function safeSearch can work for any type, so that's actually fine. But you also try to print the Maybe a value. Using print requires a Show instance, and the instance for Maybe a requires there to also be a Show instance for a. Because there is nothing saying what type a is, the compiler has no way of finding the appropriate Show instance for it, so it has to abort compilation with an error.
The most straightforward way to solve it is to add a type annotation (either of the list, or the Maybe a value resulting from safeSearch). Something like this:
main = print (safeSearch ([] :: [Int]) 5)
(This is what the error message is talking about when it says an ambiguous type variable is preventing a Show constraint from being solved, and that the probable fix is to add a type annotation)
Note that this sort of issue is rarely a problem in "real" code. Normally if you have a list processed into another structure with a related type, you will have other code that does something with the elements or the result, or that produced the list (which isn't always empty). You wouldn't normally write a program that does nothing but process an always-empty list and print the result, except for these kinds of quick tests. So normally, when there is that other code as well, there will be enough context for the compiler to deduce the type of your empty list, and the extra type annotations will not be needed. So this kind of extra type annotation is not usually considered a serious burden that needs to be avoided, because they are hardly ever needed in "real" code. You just code as you want, and on the occassion that a compile error makes your realise you need an annotation you simply add it and move on.
If you do this kind of quick check in GHCi rather than writing a full program with a main function, then you also would not have needed the extra type annotation. This is because GHCi has the ExtendedDefaultRules language extension turned on by default. The "default rules" are conditions when GHC will choose a type for you instead of throwing an "ambiguous type" error. The normal default rules are pretty strict, and really only designed for defaulting numeric constraints (like Num a or Real a, etc). They do not apply to your original example. The "extended default rules" apply more often to avoid needing lots of type signatures in the interactive interpreter (since there you enter one line at a time, instead of the compiler being able to see the full module to infer types from usage). In this case entering print (safeSearch [] 5) at the interpreter prompt will work because it defaults the returned type to Maybe (), and it just so happens that printing Nothing :: Maybe () produces the same output as it would if it had correctly guessed the type you actually meant.
But in almost any real program, defaulting a type variable to () will be a stupid thing to do that makes things work less, so I do not recommend getting into the habit of enabling ExtendedDefaultRules in an actual module. Just add the type annotation, or do quick checks in the interpreter instead of in a module.
What you've written works great for any real-world use case. It only fails when someone writes print (safeSearch [] x) - a literal empty list, with no context to tell what result type is expected. It works fine if they pass in a nonempty list, or a list expression that happens to evaluate to an empty list, or if they use the result in a way that lets type inference figure out what was intended.
Further, there is really no way to write the function so that it works when passed a contextless empty list. The burden to make the types clear is necessarily placed on call sites, not the definition. The comments on your question have already shown how to do this; you only have to be that explicit when you're calling your function in a way that's obviously useless.
I came across this error message in another question and I would like to know what is the meaning of the $: part of the signature, please?
Cannot resolve caller index(Str: Str, Any); none of these signatures match:
(Str:D $: Cool:D $needle, *%_)
(Str:D $: Str:D $needle, *%_)
(Str:D $: Cool:D $needle, Cool:D $pos, *%_)
(Str:D $: Str:D $needle, Int:D $pos, *%_)
The $: is two distinct unrelated tokens, a $ and a :, that have been smooshed together.
The $ represents a single item1 aka a scalar2.
The single item / scalar hasn't been given a name, so there's no way to reference it. And there's already enough of a parameter (the Str:D) to let you and the compiler know that this parameter is a scalar (a single string). Either way, the $ is redundant and Elizabeth has made a related change.
The : is a special parameter separator. (The usual parameter separator is a comma ,.)
It may only be used immediately after the first parameter of a method or standalone signature. It may not be used in the signature of a routine that is not a method.
If used as a parameter separator after the first parameter in a signature, it marks that parameter as corresponding to a method's "invocant".
(If not used, the invocant parameter is implicit.)
The corresponding invocant argument will arrive anyway, and be aliased to self, whether or not the signature explicitly lists an invocant parameter. But if the invocant parameter is explicitly specified, it's possible to give it an additional/alternate name and/or explicitly constrain its type.
Crazy over-the-top footnotes for added entertainment. If they confuse you, just forget you ever read them.
1 A single item refers to data that is naturally a single thing, like the number 42, OR data that is naturally a composite thing (like an array) that is being treated like it's a single thing (like an array). (Did you see what I did there?) I like to point out the mnemonic that a $ symbol is like an S (for single) overlaid with an I (for item), or vice-versa. To me this represents the idea of emphasizing the single item nature of any data, hiding any plural aspect even if it's actually an array or other composite data item.
2 "scalar" is a traditional computing term. Wikipedia's Scalar disambiguation page lists "Variable (computing), or scalar, an atomic quantity that can hold only one value at a time" as a definition. Also, a single item aka scalar (all lowercase) is often/usually a Scalar (uppercase S), a special case of a single item that's a Single Item container that contains a Single Item (which can be composite data being treated as a single thing).
The : mark the first argument as an invocant.
my $word = "bananarama";
say $word.index( "r", 0 );
In this case, it indicates the invocant is going to be treated as an scalar, since it's constrained by a single $
In a Haskell source file, I can write
a = 1
and I had the impression that I have to write the same in GHCi as
let a = 1
, for a = 1 in GHCi gives a parse error on =.
Now, if I write
a = 1
a = 2
in a source file, I will get an error about Multiple declaration of a, but it is OK to write in GHCi:
let a = 1
let a = 2
Can someone help clarify the difference between the two styles?
Successive let "statements" in the interactive interpreter are really the equivalent of nested let expressions. They behave as if there is an implied in following the assignment, and the rest of the interpreter session comprises the body of the let. That is
>>> let a = 1
>>> let a = 1
>>> print a
is the same as
let a = 1 in
let a = 1 in
print a
There is a key difference in Haskell in having two definitions of the same name and identical scopes, and having two definitions of the same name in nested scopes. GHCi vs modules in a file isn't really related to the underlying concept here, but those situations do lead you to encounter problems if you're not familiar with it.
A let-expression (and a let-statement in a do block) creates a set of bindings with the same scope, not just a single binding. For example, as an expression:
let a = True
a = False
in a
Or with braces and semicolons (more convenient to paste into GHCi without turning on multi-line mode):
let { a = True; a = False} in a
This will fail, whether in a module or in GHCi. There cannot be a single variable a that is both True and False, and there can't be two separate variables named a in the same scope (or it would be impossible to know which one was being referred to by the source text a).
The variables in a single binding set are all defined "at once"; the order they're written in is not relevant at all. You can see this because it's possible to define mututally-recursive bindings that all refer to each other, and couldn't possibly be defined one-at-a-time in any order:
λ let a = True : b
| b = False : a
| in take 10 a
[True,False,True,False,True,False,True,False,True,False]
it :: [Bool]
Here I've defined an infinite list of alternating True and False, and used it to come up with a finite result.
A Haskell module is a single scope, containing all the definitions in the file. Exactly as in a let-expression with multiple bindings, all the definitions "happen at once"1; they're only in a particular order because writing them down in a file inevitably introduces an order. So in a module this:
a = True
a = False
gives you an error, as you've seen.
In a do-block you have let-statements rather than let-expressions.2 These don't have an in part since they just scope over the entire rest of the do-block.3 GHCi commands are very like entering statements in an IO do-block, so you have the same option there, and that's what you're using in your example.
However your example has two let-bindings, not one. So there are two separate variables named a defined in two separate scopes.
Haskell doesn't care (almost ever) about the written order of different definitions, but it does care about the "nesting order" of nested scopes; the rule is that when you refer to a variable a, you get the inner-most definition of a whose scope contains the reference.4
As an aside, hiding an outer-scope name by reusing a name in an inner scope is known as shadowing (we say the inner definition shadows the outer one). It's a useful general programming term to know, since the concept comes up in many languages.
So it's not that the rules about when you can define a name twice are different in GHCi vs a module, its just that the different context makes different things easier.
If you want to put a bunch of definitions in a module, the easy thing to do is make them all top-level definitions, which all have the same scope (the whole module) and so you get an error if you use the same name twice. You have to work a bit more to nest the definitions.
In GHCi you're entering commands one-at-a-time, and it's more work to use multi-line commands or braces-and-semicolon style, so the easy thing when you want to enter several definitions is to use several let statements, and so you end up shadowing earlier definitions if you reuse names.5 You have to more deliberately try to actually enter multiple names in the same scope.
1 Or more accurately the bindings "just are" without any notion of "the time at which they happen" at all.
2 Or rather: you have let-statements as well as let-expressions, since statements are mostly made up of expressions and a let-expression is always valid as an expression.
3 You can see this as a general rule that later statements in a do-block are conceptually nested inside all earlier statements, since that's what they mean when you translate them to monadic operations; indeed let-statements are actually translated to let-expressions with the rest of the do-block inside the in part.
4 It's not ambiguous like two variables with the same name in the same scope would be, though it is impossible to refer to any further-out definitions.
5 And note that anything you've previously defined referring to the name before the shadowing will still behave exactly as it did before, referring to the previous name. This includes functions that return the value of the variable. It's easiest to understand shadowing as introducing a different variable that happens to have the same name as an earlier one, rather than trying to understand it as actually changing what the earlier variable name refers to.
I am new to Prolog and therefore need help with the following task.
I have the programm:
do(save) :- save_bal(bad).
do(act) :- save_bal(good), inc(good).
do(comb) :- save_bal(good), inc(bad).
save_bal(good) :- savMoney(X), depPeople(Y), Min is Y * 1000, X >= Min.
save_bal(bad) :- not(save_bal(good)).
inc(good) :- earn(Z), depPeople(Y), MinE is 3000 + Y * 400, Z >= MinE.
inc(bad) :- not(inc(good)).
savMoney(30000).
earn(60000).
depPeople(4).
My task is to rewrite this programm, so the numbers 30000, 60000 and 4 is set by a user input. How can I do this?
I tried:
:- read(A), savMoney(A).
:- read(B), earn(B).
:- read(C), depPeople(C).
But that won't work.
Can someone point me in the right direction?
Thanks in advance!
Prolog is an homoiconic language, then the first step you should take is to declare which predicate are data, and which are (just to say) logic constraints on the data.
Then, add near top of file (just a stylistic hint) the declarations
:- dynamic(savMoney/1).
:- dynamic(earn/1).
:- dynamic(depPeople/1).
then you can add a service predicate, say user_update_store/1, like
user_update_store(Entry) :-
AccessValueCurr =.. [Entry, ValueCurr],
(retract(AccessValueCurr) -> true ; ValueCurr = 0),
format('enter value for ~s (current is ~w):', [Entry, ValueCurr]),
read(NewValue),
% validate it's a number etc...
StoreNewValue =.. [Entry, NewValue],
assertz(StoreNewValue).
now you can start your user interface:
?- maplist(user_udpdate_store, [savMoney,earn,depPeople]).
this code should work for every (ISO compliant) Prolog. Note: I didn't tested it...
HTH
CapelliC provided an excellent (better) answer while I was busy typing away at this monstrosity. In fact, I didn't end up addressing the question in your title, because you were passing parameters just fine. Instead I wrote about assertz/1 and retract/1. However, I taught myself a fair amount while composing it and you might also find it informative.
In your example code, we have 3 facts declared with the predicates savMoney/1, earn/1, depPeople/1'. We then have a number of rules that determine values based on these facts. A rule is of the form :- ., and which I sometimes read to myself as "<head> is true if <body> is true". We can think of a fact as a rule of the form :- true, e.g.,savMoney(30000) :- true.`, which we might read as "30000 is savMoney if true is true", and true is true or we're all screwed. (BTW, is 'savMoney' short for saved money?)
A directive is of the form :- <body>.. It is like a rule that must be tested in order for the program (or world) to be true (this is more evocative than accurate, because, as you've seen, when a directive fails the whole program-world is not false, we just get a warning). When we consult a prolog file, we add new rules and facts to our program-world, and these can even be impossible nonsense statements like a :- \+ a. "a is true if not-a is true"1. That contradiction will cause cause a stack overflow if you query ?- a., but the program will load just fine. However, directives have to be evaluated and settled while the program loads in the order they are encountered:
This program will throw a stack overflow error when the interpreter consults it.
a :- \+ a.
:- a.
This program will throw an undefined procedure error, because it is being directed to prove a before a has been entered into the database.
:- a.
a :- \+ a.
When we have a directive like :- read(A), savMoney(A)., it's not saying "read the value of user input into A and then set saveMoney to A". Instead, it's saying something more like, "if this program is loaded, then A is a value read in from user input and A is savMoney." Suppose you run the program and enter 100 at the first prompt (the plain prompt is |). What happens?
prolog unifies the variable A with 100.
prolog tries to prove savMoney(100).
it replies Warning: Goal (directive) failed: user:(read(_G2072),savMoney(_G2072)).
This is because, while savMoney(30000) is true, savMoney(100) is not. A directive does not assert the contents of its body, it only tells prolog to prove those contents.
What you are trying to do is allow the user to assert a previously unknown fact into the database. As indicated by mbratch, this requires using the predicate assertz/12. However, predicted that be changed during run-time are differentiated from standard predicates.
If you try to define a reestablished predicate in a program, you'll get an error. E.g., consult a file consisting of the following declaration:
length(2, y).
You'll receive an error:
ERROR: /Users/aporiac/myprolog/swi/studies/test.pl:18:
No permission to modify static procedure `length/2'
Defined at /opt/local/lib/swipl-6.2.6/boot/init.pl:2708
This tells us that 'length/2' is static and that it is already defined in init.pl file at line 2708.
The same happens if you try to assert a static predicate with assertz/1. You can try this by querying assertz(savMoney(100)) in swipl. In order to add new facts or rules about a predicate, we have to declare the predicate to be dynamic.
This is accomplished with dynamic/1. To assure that prolog knows which of our predicates are to be counted as dynamic, we give it a directive like so3:
:- dynamic savMoney/1.
If you've added that to your file (before you define the predicate), you can then query ?- assertz(savMoney(100)). to add the new fact to the database. Now, if you query ?- savMoney(X), you'll get
X = 30000;
X = 100.
There are now two possible values for X, because we've added another fact to the database.
Of course, in your case, you don't want to keep adding values to savMoney/1, you want to be able to update and replace the value.
That calls for retract/1 (If you think there's a chance that more than one occurrence the asserted predicate could get added at some point, then you can use retractall/1 to clear all instances). Now we can write a rule like the following:
set_saved(Amount) :-
retract( savMoney(_) ),
assertz( savMoney(Amount) ).
set_saved(Amount) is true if savMoney(_) can be retracted and removed from the database and the new fact savMoney(Amount) can be asserted.
I've just seen that CapelliC has provided a simple input interface, and a much more concise solution to the problem, but here's my version of your example program in case it might be informative. (I didn't actually get around to adding the prompt and input, but querying, e.g., ?- set_saved(100), does what you'd expect).
:- dynamic [ savMoney/1,
earn/1,
depPeople/1 ].
do(save) :- save_bal(bad).
do(act) :- save_bal(good), inc(good).
do(comb) :- save_bal(good), inc(bad).
save_bal(good) :- savMoney(X), depPeople(Y), Min is Y * 1000, X >= Min.
save_bal(bad) :- not(save_bal(good)).
inc(good) :- earn(Z), depPeople(Y), MinE is 3000 + Y * 400, Z >= MinE.
inc(bad) :- not(inc(good)).
savMoney(30000).
earn(60000).
depPeople(4).
set_saved(Amount) :-
retract( savMoney(_) ),
assertz( savMoney(Amount) ).
set_earned(Amount) :-
retract( earn(_) ),
assertz( earn(Amount) ).
set_people_in_department(Number) :-
retract( depPeople(_) ),
assertz( depPeople(Number) ).
report([Saved, Earned, People]) :-
Saved = savMoney(_) , Saved,
Earned = earn(_) , Earned,
People = depPeople(_), People.
\+/1 is the standard negation operator in swi-prolog and not/1 is depreciated.
assert/1 is equivalent to, and depreciated in favor of, assertz/1. asserta/1 asserts the fact or clause as the first instance of the predicate at hand, while assertz/1 asserts it as the last. (Cf. the manual section on the Database).
Of course, this goes against the interpretation of the directive I suggested before. My interpretation fits when you're using 'normal' predicates in a directive. But, most often, we see directives used for special predicates like in module declarations (:- module(name, [<list of exported predicates>]) or module imports (:- use_module([<list of modules>])).
Just started learning Haskell.
I have an empty source file with this inside:
pe :: (Integral a) => a -> a
pe y = sum [x | x <- [1..y-1], x `mod` 3 == 0 || x `mod` 5 == 0]
Now if I ghci this, I can call pe like so:
*Main> pe 1000
233168
How do I call it from within my source file? If I have
pe 1000
it returns a cryptic error:
GHC stage restriction: `pe'
is used in a top-level splice or annotation,
and must be imported, not defined locally
In the expression: pe 1000
Do I need to declare it in main or something?
Yes, you need to hook it up to your main function. For example,
main = print (pe 1000)
If you want to have multiple calls, you can combine them with do-notation:
main = do
print (pe 500)
print (pe 1000)
A Haskell source file contains a sequence of definitions, not expressions. So you can't just put an expression in the top level of the file, you have to put it inside the body of a definition. So since pe 1000 is not a definition, you get an error.
But why such a cryptic error message? GHC has an extension called Template Haskell, which allows you to programmatically create definitions at compile time. To achieve this it allows you to put an expression in a place where usually only definitions are allowed and evaluates the expression at compile time and replace the expression with its result (which must be a definition) - this is called splicing and the expression is then called a splice. Such a splice needs to meet two requirements:
Any identifiers used in the expression must be defined in a different source file (this is required so that the used functions are already compiled when the expression is encountered and thus can be called during compile-time)
The type of the expression must be a Template Haskell type which represents a valid definition.
So since your expression pe 1000 appears somewhere where only definitions are allowed, GHC assumes it is a splice. However since it does not meet the first of the above criteria, i.e. it is defined in the current file instead of a different file, GHC complains about that. Of course it doesn't meet the second condition either, but GHC hasn't gotten to that yet, when it produces the error message. If pe were defined in a different source file, you'd have gotten an error message complaining about the fact that pe has the wrong type.