Pretty new to Prolog, but I'm trying to implement a context-free grammar and I'm having an issue passing a test case with the rules I have.
I've tried changing the order of my rules to seem more logically correct, but I can't seem to get consistent correct outputs and I continue to get the same stack error. I think it has something to do with vp --> vp, np. being recursive, but if that's the case, then why doesn't np --> np, pp. give me an error as well? My code is below:
:- use_module(library(tabling)).
:- table s/2.
s --> np, vp.
np --> det, n.
np --> np, pp.
vp --> vp, pp.
vp --> v, np.
pp --> p, np.
det --> [the].
n --> [cop].
n --> [criminal].
n --> [street].
v --> [chased].
p --> [in].
p --> [by].
Asking this to the query ideally should return true:
$- s([the,cop,chased,the,criminal], []).
And asking this should return false:
$- s([the, cop, the, criminal, chased], []).
I've tried both and they just give me the same error:
Stack limit (0.2Gb) exceeded
Stack sizes: local: 0.2Gb, global: 22Kb, trail: 5Kb
Stack depth: 1,561,893, last-call: 0%, Choice points: 1,561,869
Probable infinite recursion (cycle):
[1,561,893] vp([length:3], _1424)
[1,561,892] vp([length:3], _1456)
Any feedback is appreciated!
The problem is that you have constructed a left recursive grammar. Indeed if we look at the rules you defined, we see:
:- use_module(library(tabling)).
:- table s/2.
s --> np, vp.
np --> det, n.
np --> np, pp.
vp --> vp, pp.
vp --> v, np.
pp --> p, np.
det --> [the].
n --> [cop].
n --> [criminal].
n --> [street].
v --> [chased].
p --> [in].
p --> [by].
Now based on how Prolog implements predicates, it can not work with such left recursive grammar, since if you call np/2, it will first call np/2, and hence we never get out of the "loop" (until the call stack overflows).
We can however use tabling here, like you somehow did with s/2, which is not necessary, since there is no left-recursive path in s that yields (directly or indirectly) s --> s, .... We need to table np/2 and vp/2, like:
:- use_module(library(tabling)).
:- table np/2.
:- table vp/2.
s --> np, vp.
np --> det, n.
np --> np, pp.
vp --> vp, pp.
vp --> v, np.
pp --> p, np.
det --> [the].
n --> [cop].
n --> [criminal].
n --> [street].
v --> [chased].
p --> [in].
p --> [by].
We then indeed can obtain the expected results:
?- s([the,cop,chased,the,criminal], []).
true.
?- s([the, cop, the, criminal, chased], []).
false.
Related
I struggle to find a solution (other than using Data.Map.fromList and toList) for the following problem:
Transform the key with a function that returns an Either String k where as usual errors are expressed as Left, and the whole transformation fails if a single key-transformation fails.
import Data.Map.Strict
mapEitherKey :: (k -> Either String k') -> Map k a -> Either String (Map k' a)
For the right-hand side v of Map k v it is easily done with mapM, because
Map k is an instance of Monad.
But none of the mapping functions offers anything functorial in the key. (I wonder whether there's a deeper reason why Map is not an instance of Bifunctor, for instance. I do see that it's not trivial because key collisions need to be taken into account.)
Any insights would be appreciated.
I'd like to second what #chi said; unless you know that the order is preserved, you'll have to reinsert the key each time. Which means that toList and then reinserting with fromList should be the best you can get asymptotically.
However, since you asked for a way to do it without those functions, I'd like to suggest using foldMapWithKey.
import Data.Monoid (Ap(..))
import qualified Data.Map as M
mapEitherKey :: (Ord k, Ord k') => (k -> Either String k') -> Map k a -> Either String (Map k' a)
mapEitherKey f = getAp . M.foldMapWithKey (\k v -> Ap (flip M.singleton v <$> f k))
The idea for this is to lift the reconstruction of the map with key k' (which we do by unioning together a bunch of singletons) into the Either String Applicative, which will short circuit if it encounters a Left.
I wrote it kind of quick and dirty, but you can refactor it to be more readable. It should be asymptotically ideal, but there might be more performant approaches.
Note that you need the Ord constraints on k and k'.
Example usage:
Prelude> f k = if k > 10 then Left "bad number" else Right $ show k
Prelude> mapEitherKey f (M.fromList [(0,0),(1,1),(2,2)])
Right (fromList [("0",0),("1",1),("2",2)])
Prelude> mapEitherKey f (M.fromList [(0,0),(1,1),(2,2),(11,11)])
Left "bad number"
I was ask to do a program in Prolog which has to be able to do a summation of pair and odd numbers with a recursive structure. The rule has the following form:
sum(N,PairSum,OddSum)
With N as the number given as parameter.
For Example: if N=5 then PairSum=4+2 and OddSum=5+3+1
My Code is the following
suma(0,0,0).
suma(N,SumPares,SumImpares) :-
N>0,
N1 is N -1,
suma(N1,SumaP,SumaI),
( (0 is mod(N,2))
-> SumPares is SumaP + (N-2)
; SumImpares is SumaI +(N-2)
).
The code compiles successfully, it fails when i run it. For example with N=5
suma(5,SumaPares,SumaImpares)
I get the following
ERROR: Arguments are not sufficiently instantiated ERROR: In: ERROR:
[12] _9750 is _9756+(2-2)
You should see 2 singleton warnings when consulting this code: SumaI and SumI only appear once in the body of second clause of procedure summation/3.
Looking at your code it seems that you wanted to use the same variable, so rename SumaI to SumI. You should now see no singleton warnings after reconsulting the code.
[edit after clarification]
After your edit you still have singleton warnings. Aside from typos the problem is that your conditional branch assigns one of the sum variables and leaves the other as-is. I believe you want something like this:
suma(0,0,0).
suma(N,SumaPares,SumaImpares) :-
N>0,
N1 is N -1,
suma(N1,SumaP,SumaI),
( 0 is mod(N,2) ->
(SumaPares is SumaP + (N-2), SumaImpares=SumaI)
; (SumaImpares is SumaI +(N-2), SumaPares=SumaP)
).
After following the advices from #gusbro and inluding some others i could make to this code to work properly. The key was in the base case that was suma(2,2,1) and not suma(0,0,0). Other problem i had was my summations in the if clause were I a do N-2 and I just have to leave the N alone and not substract anything. Here is the working code:
suma(2,2,1).
suma(N,SumaPares,SumaImpares) :-
N>0,
N1 is N -1,
suma(N1,SumaP,SumaI),
( 0 is mod(N,2) ->
(SumaPares is SumaP + N, SumaImpares is SumaI)
; (SumaImpares is SumaI +N, SumaPares is SumaP)
).
Thanks a lot for the help.
I was looking at the examples of writer monad to understand how it works and almost all of those looks like a list writer monad. I know a list writer monad is a type of writer monad. But what really is a writer monad in lay-mans terms.
In lay terms, the writer monad is the monad that lets you "write" items to a "log" while you produce a value. When you're done, you end up with the value you produced and the log that contains all the stuff you wrote. To put it another way, it is the monad whose side effects are "writing things to a log".
Let's make this more concrete with examples of both the list writer and the (generic) writer monads. I'll use Haskell here, since it is the original context in which Monads for Functional Programming were described.
The List Writer Monad
I assume that the "list writer" monad is one that logs an item (of some type we'll call w) into a list of items (of type [w], of course). It also produces a value of type a. (See the note at the bottom if you get errors using this code yourself.)
newtype ListWriter w a = ListWriter { runListWriter :: ([w], a) }
instance Monad (ListWriter w) where
return a = ListWriter ([], a) -- produce an a, don't log anything
ListWriter (ws, a) >>= k =
let ListWriter (xs, a') = k a -- run the action 'k' on the existing value,
in ListWriter (ws ++ xs, a') -- add anything it logs to the existing log,
-- and produce a new result value
-- Add an item to the log and produce a boring value.
-- When sequenced with >>, this will add the item to existing log.
tell :: w -> ListWriter w ()
tell w = ListWriter ([w], ())
ex1 :: ListWriter String Int
ex1 = do
tell "foo"
tell "bar"
return 0
(NB: This is equivalent to ex1 = tell "foo" >> tell "bar" >> return 0, demonstrating the use of tell with >> to add an item to the log.)
If we evaluate runListWriter ex1 in GHCi, we see that it wrote "foo" and "bar" to the log and produced the result value 0.
λ> runListWriter ex1
(["foo","bar"],0)
The (Generic) Writer Monad
Now, let's see how we turn this into the generic writer monad. The writer monad works with any sort of thing that can be combined together, not just a list. Specifically, it works with any Monoid:
class Monoid m where
mempty :: m -- an empty m
mappend :: m -> m -> m -- combine two m's into a single m
Lists are a Monoid with [] and (++) as mempty and mappend respectively. A non-list example of a Monoid is sums of integers:
λ> Sum 1 <> Sum 2 -- (<>) = mappend
Sum {getSum = 3}
The writer monad is then
newtype Writer w m = Writer { runWriter :: (w, m) }
Instead of a list of w's, we just have a single w. But when we define the Monad, we ensure that w is a Monoid so we can start with an empty log and append a new entry to the log:
instance Monoid w => Monad (Writer w) where
return a = Writer (mempty, a) -- produce an a, don't log anything
Writer (w, a) >>= k =
let Writer (x, a') = k a -- we combine the two w's rather than
in Writer (w <> x, a') -- (++)-ing two lists
Note the differences here: we use mempty instead of [] and (<>) instead of (++). This is how we generalize from lists to any Monoid.
So the writer monad is really a generalization of the list monad to arbitrary things that can be combined rather than just lists. You can use lists with the Writer to get something (almost) equivalent to ListWriter. The only difference is that you have to wrap your logged item in a list when you append it to the log:
ex2 :: Writer [String] Int
ex2 = do
tell ["foo"]
tell ["bar"]
return 0
but you get the same result:
λ> runWriter ex2
(["foo","bar"],0)
This is because instead of logging "an item that will be put in a list", you are logging "a list". (This does mean that you can log multiple items at the same time by passing a list of more than one element.)
For an example of a non-list use of Writer, consider counting the comparisons a sort function makes. Each time your function make a comparison, you can tell (Sum 1). (You can tell someone. Get it? Is this thing on?) Then, at the end, you'll get back the total count (i.e., the sum) of all of the comparisons along with the sorted list.
NOTE: If you try to use these ListWriter and Writer definitions yourself, GHC will tell you that you are missing Functor and Applicative instances. Once you have the Monad instance, you can write the others in its terms:
import Control.Monad (ap, liftM)
instance Functor (ListWriter w) where
fmap = liftM
instance Applicative (ListWriter w) where
pure = return
(<*>) = ap
And likewise for Writer. I elided them above for clarity.
I am working on a proof which I was able to reduce to “of_int i = 0 ==> i = 0”. This seemed like a simple application of the rule “of_int_eq_0_iff” however I was unable to successfully apply this rule.
On further probing I found that I was unable to prove the following lemma
lemma of_int_eq_0_imp1: “of_int i = 0 ==> i = 0”
by any means whatsoever. That is, unless I declare the lemma within the context ring_char_0. Then the lemma can easily be proved as follows:
context ring_char_0 begin
lemma of_int_eq_0_imp1: “of_int i = 0 ==> i = 0”
using of_int_eq_iff [of i 0] by simp
end
But then I cannot apply this lemma outside of this context, which is what my main theorem requires (it resides within a different context).
Any help would be greatly appreciated.
The fact that you can only prove your lemma inside ring_char_0 should make you suspicious. The reason for this is that the lemma of_int_eq_0_iff is defined in the context of ring_char_0 itself. You can see this by typing e.g.
declare [[show_sorts]]
thm of_int_eq_0_iff
> (of_int (?z∷int) = (0∷?'a∷ring_char_0)) = (?z = (0∷int))
The reason for this is that in a ring with a characteristic k ≠ 0, this does not hold. In such a ring, of_int n will be zero for all multiples n of k, despite n not being 0.
If your original goal reduces to of_int i = 0 ==> i = 0 then maybe your original goal only holds for rings of characteristic 0, or you need a different proof, one that does not require of_int i = 0 ==> i = 0.
fighting with f# - the fight is in the realm of Trees - specifically to count the number of nodes. This is of real interest as the program I would like to eventually code in F# concerns multi-way trees, unfortunately it has got off to a bit of a troublesome start - I hope you maybe able to help!
Problem 61 of the 99 f# series, asks to count the leaves of a binary Tree. The solution (given below) counts the nodes, but my problem is not understanding
how the double recursion works loop left (fun lacc -> loop right..)
what cont (branchF x lacc racc) is, my impression was that cont was the "abc" function, but this takes only two parameters...
loop t id the id is of type unit - i don't see how this is implied
basically not understanding this, or the order in which it flows through the tree (debug & step through not proving helpful) If there are simpler examples, pre-reading recommendations etc. then please direct me to them.
Many thanks for any help, the solution code in question is below:
Cheers
td
type 'a Tree = Empty | Branch of 'a * 'a Tree * 'a Tree
let foldTree branchF emptyV t =
let rec loop t cont =
match t with
| Empty ->
cont emptyV
| Branch (x, left, right) ->
loop left (fun lacc ->
loop right (fun racc ->
cont (branchF x lacc racc)))
loop t id
let counLeaves tree =
foldTree (fun abc lc rc ->
if lc + rc = 0 then 1
else 1 + lc + rc) 0 tree
let Tree1 = Branch ('x', Branch ('x', Empty, Empty),Branch ('x', Empty, Branch ('x', Empty, Branch ('x', Empty, Empty))))
let result = counLeaves Tree1
As the name implies, foldTree defines the fold function over the custom Tree type.
A naive way of defining a foldTree could be:
let rec foldTreeNaive accFun init = function
| Empty -> init
| Branch (x, left, right) ->
let lacc = foldTreeNaive accFun init left
let racc = foldTreeNaive accFun init right
accFun x lacc racc
The problem with this function is that it could potential make very deep recursive calls if the tree being folded over is deep, since the recursive calls must complete for a node before the accumulator function can be called. For example the following causes a stack overflow exception:
let unbalanced = [1..100000] |> List.fold (fun t i -> Branch(i, t, Empty)) Empty
let nodeCount = foldTreeNaive (fun _ lc rc -> lc + rc + 1) 0 unbalanced
The usual way to avoid such stack overflows is to make the function tail recursive, however this seems impossible in this case since there are two recursive calls to make, instead of the one required when folding over lists.
foldTree is defined using the local loop function. This function is interesting in that it is defined using continuation passing style. In CPS, each function takes an additional 'continuation' function which is passed the result of the computation and is responsible for deciding what happens next. Note that loop is tail recursive and so avoids the overflow problem of foldTreeNaive.
The type of the loop function is:
Tree<'a> -> ('b -> 'c) -> 'c
where 'a is the type of nodes in the tree, 'b is the accumulator type, and 'c is the result of the continuation function.
In the case of a leaf node, the continuation is passed the empty accumulator value passed to the foldTree function.
When folding over a non-empty tree in the Branch case, the result of the fold depends on the results for the left and right subtrees. This is done recursively, first by folding over the left subtree, then the right. For the recursive call over the left subtree, loop must build a new continuation to receive the result, this is the
(fun lacc ->
loop right (fun racc ->
cont (branchF x lacc racc))
function. What this continuation does is to make a recursive call over the right subtree, passing yet another continuation to receive the result of that fold. When that continuation is called, the results for the left and right subtrees are available in lacc and racc. At this point the accumulation function for the node can be called with the value for the current node and the results for the left and right subtrees. The result of this function is then passed to the original continuation passed to loop.
The loop function is then invoked by the foldTree function in the line:
loop t id
Here, id is the continuation which will receive the result of the fold for the root node of the tree. Since this is the value required, id just returns its argument without modification.
You might also find this description of fold for binary trees useful.