Now you've had time to chew on it and come up with a solution, here's another way of attacking it.
I always try to state in plain english what the solution is, then code that. In this case:
'uniqll is true if the length of a sublist not a member of a list containing the lengths for the rest of the list'
uniqll([],[]).
uniqll([H|T], [LenH|LensSoFar]) :-
uniqll(T, LensSoFar),
length(H, LenH),
not(member(LenH, LensSoFar)).
If it's not clear what it happening, the prolog 'trace' predicate is your friend.. in fact it's most important when you're trying to get prolog to do the dirty work for you / come up with a minimal solution.
[trace] 10 ?- uniqll([[2,3],[4,5]],X).
Call: (6) uniqll([[2, 3], [4, 5]], _G1276) ? creep
Call: (7) uniqll([[4, 5]], _G1360) ? creep
Call: (8) uniqll([], _G1363) ? creep
Exit: (8) uniqll([], []) ? creep
Call: (8) length([4, 5], _G1362) ? creep
Exit: (8) length([4, 5], 2) ? creep
^ Call: (8) not(member(2, [])) ? creep
^ Exit: (8) not(user:member(2, [])) ? creep
Exit: (7) uniqll([[4, 5]], [2]) ? creep
Call: (7) length([2, 3], _G1359) ? creep
Exit: (7) length([2, 3], 2) ? creep
^ Call: (7) not(member(2, [2])) ? creep
^ Fail: (7) not(user:member(2, [2])) ? creep
Fail: (6) uniqll([[2, 3], [4, 5]], _G1276) ? creep
false.
And for success:
[trace] 11 ?- uniqll([[2,3],[4]],X).
Call: (6) uniqll([[2, 3], [4]], _G1479) ? creep
Call: (7) uniqll([[4]], _G1560) ? creep
Call: (8) uniqll([], _G1563) ? creep
Exit: (8) uniqll([], []) ? creep
Call: (8) length([4], _G1562) ? creep
Exit: (8) length([4], 1) ? creep
^ Call: (8) not(member(1, [])) ? creep
^ Exit: (8) not(user:member(1, [])) ? creep
Exit: (7) uniqll([[4]], [1]) ? creep
Call: (7) length([2, 3], _G1559) ? creep
Exit: (7) length([2, 3], 2) ? creep
^ Call: (7) not(member(2, [1])) ? creep
^ Exit: (7) not(user:member(2, [1])) ? creep
Exit: (6) uniqll([[2, 3], [4]], [2, 1]) ? creep
X = [2, 1].
As a side effect, the list when True, the list at the end is the list of the lengths.
Prolog is just so damn cool and elegant.