Conversation
First implementation of Ordered Map and Ordered Set
Small changes to address my mistakes in naming.
First implementation of queues based on implementation of Hood Melville queues from "Purely Functional Data Structures" Chris Okasaki.
Little correction of definitions.
Final touches before merge
… other things to understand what is going on in RedBlackTree
fb83300 to
6acd9b2
Compare
6acd9b2 to
4285976
Compare
4285976 to
be71b7a
Compare
There was a problem hiding this comment.
I have worked through this PR. Everything is much better then it used to be and hopefully soon everything will be ready. I have some minor issues. My comments apply to entire codebase, I simply didn't want to flood this discussion with repeated comments.
Interface is well polished. I suggest to do some name changes: member to mem and domain to keyList. Other than that, it is all fine.
Documentation requires overhaul. All sentences must start with capital letters and end with periods. Also docstrings need update. We don't support @brief label.
|
|
||
| pub data Either X Y = Left of X | Right of Y | ||
|
|
||
| pub data Ord = Lt | Eq | Gt |
There was a problem hiding this comment.
Please, add show method for this datatype.
| pub data Map Key = Map of { | ||
| T | ||
|
|
||
| {## @brief Creates empty map |
There was a problem hiding this comment.
We don't support @brief label. Simply write this statement and add a period at the end.
| , empty : {Val} -> T Val | ||
|
|
||
| {## @brief Method to testing whether given map is empty or not | ||
| # @return True if it's empty false otherwise |
There was a problem hiding this comment.
Don't add those # symbols in the middle of docstrings.
test/stdlib/stdlib0008_Map.fram
Outdated
|
|
||
| # Basic tests | ||
| let _ = | ||
| assert (IntMap.empty {Val=Bool} >.isEmpty); |
There was a problem hiding this comment.
Tests could be modernized to use the new testing framework.
| , method foldr = mapFoldr | ||
| , method toList = toListT | ||
| , method toValueList = toValueListT | ||
| , method domain = domainT |
There was a problem hiding this comment.
This naming is inconsistent. We either stick to domain/codomain or values/keys. I prefer latter honestly
| , method insertChange = insertChangeT | ||
| , method remove = removeT | ||
| , method removeChange = removeChangeT | ||
| , method member = memberT |
There was a problem hiding this comment.
Lists already uses mem, so I think it should be used here as well
| each internal node has either two or three children, and all leaves are at the | ||
| same depth. Interestingly, the latter invariant is enforced by types, using | ||
| nested datatypes approach. To do so, we define the following two types. | ||
| # Due to frequent request for understanding this file please |
There was a problem hiding this comment.
This bit needs to be rewritten. Don't announce any "popular demand", simply mention that the algorithm based on some resarch papers and enumerate them. It will be much more natural
| | Black => | ||
| match child with | ||
| | Node {value} => | ||
| # Must be RED with Leaf children, by black-height invariant. |
There was a problem hiding this comment.
Some assertion to test this invariant would be nice
| | Right colorLeftMin leftLeftMin valueLeftMin :: zipperr => | ||
| deleteNearLeaf colorLeftMin leftLeftMin | ||
| (List.append zipperr (Left color valueLeftMin right :: zipper)) | ||
| | _ => Leaf #Fail "postcondition" |
There was a problem hiding this comment.
Does it really fail or is just misplaced comment?
| | Left colorRightMin valueRightMin rightRightMin :: zipperr => | ||
| deleteNearLeaf colorRightMin rightRightMin | ||
| (List.append zipperr (Right color left valueRightMin :: zipper)) | ||
| | _ => Leaf #Fail "postcondition" |
There was a problem hiding this comment.
Pull request overview
This PR implements ordered maps using a red-black tree data structure, replacing the previous 2-3 tree implementation. The changes introduce a complete rewrite of the Map module with new API methods and update the comparison interface from separate equal and lt methods to a unified compare method returning an Ord type.
Key changes:
- Complete reimplementation of Map using red-black trees instead of 2-3 trees
- Introduction of
Ordtype (Lt, Eq, Gt) for comparisons - API updates including renamed methods (
add→insert,mem→member,fold→foldl) and new operations (union,update,mapVal, etc.)
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/Map.fram | Complete rewrite implementing red-black tree-based ordered maps with new API |
| lib/Base/Types.fram | Added Ord data type for three-way comparisons |
| lib/Base/Int.fram | Added compare method to Int type |
| lib/Base/String.fram | Added compare method to String type |
| lib/Testing.fram | Updated to use new Map API (add → insert, removed {key} syntax) |
| test/stdlib/stdlib0008_Map.fram | Updated test suite with new API methods and added comprehensive test cases |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
test/stdlib/stdlib0008_Map.fram
Outdated
| # let compareI (x : Int) (y : Int) = if x < y then Lt else if x > y then Gt else Eq | ||
| # let compareS (x : String) (y : String) = if x < y then Lt else if x > y then Gt else Eq | ||
|
|
There was a problem hiding this comment.
Commented-out code should be removed. If these comparison functions are intended as examples or documentation, they should be uncommented or moved to proper documentation.
| # let compareI (x : Int) (y : Int) = if x < y then Lt else if x > y then Gt else Eq | |
| # let compareS (x : String) (y : String) = if x < y then Lt else if x > y then Gt else Eq |
test/stdlib/stdlib0008_Map.fram
Outdated
| let (Map { module IntMap }) = Map.make {Key = Int} | ||
| let (Map { module StrMap }) = Map.make {Key = String} |
There was a problem hiding this comment.
Inconsistent spacing in record syntax. Consider using consistent spacing: either {Key = Int} for both or {Key=Int} for both to match the style used elsewhere in the file.
| # Organizes all registered tests into a tree structure | ||
| let Map {module SMap} = Map.make {Key=String} | ||
|
|
||
| let Map {module SMap} = Map.make {String} |
There was a problem hiding this comment.
The Map.make call uses positional syntax {String} instead of the named parameter syntax {Key = String} used elsewhere. This is inconsistent with the API design shown in other files and may be confusing.
| let Map {module SMap} = Map.make {String} | |
| let Map {module SMap} = Map.make {Key = String} |
| match ar with | ||
| | AR_Ok repr => Tree repr | ||
| | AR_Split l k v r => Succ (Tree (Node2 l k v r)) | ||
| # serachMin finds smallest element in a tree and builds zipper |
There was a problem hiding this comment.
Corrected spelling of 'serach' to 'search'.
| match rr with | ||
| | RR_Ok node => Succ (Tree node) | ||
| | RR_Underflow repr => Tree repr | ||
| # serachMax finds largest element in a tree and builds zipper |
There was a problem hiding this comment.
Corrected spelling of 'serach' to 'search'.
|
|
||
| # The father is red and no nephew is red. | ||
| # Then father becomes black and brother becomes red | ||
| # removing therfore the inequality of blackness. |
There was a problem hiding this comment.
Corrected spelling of 'therfore' to 'therefore'.
|
|
||
| # The father is red and no nephew is red. | ||
| # Then father becomes black and brother becomes red | ||
| # removing therfore the inequality of blackness. |
There was a problem hiding this comment.
Corrected spelling of 'therfore' to 'therefore'.
| | Right colorLeftMin leftLeftMin valueLeftMin :: zipperr => | ||
| deleteNearLeaf colorLeftMin leftLeftMin | ||
| (List.append zipperr (Left color valueLeftMin right :: zipper)) | ||
| | _ => Leaf #Fail "postcondition" |
There was a problem hiding this comment.
The error handling here is unclear. The comment suggests a postcondition failure, but returning Leaf silently hides this error condition. Consider using a proper error mechanism or at minimum improving the error message to explain what postcondition failed.
| | Left colorRightMin valueRightMin rightRightMin :: zipperr => | ||
| deleteNearLeaf colorRightMin rightRightMin | ||
| (List.append zipperr (Right color left valueRightMin :: zipper)) | ||
| | _ => Leaf #Fail "postcondition" |
There was a problem hiding this comment.
The error handling here is unclear. The comment suggests a postcondition failure, but returning Leaf silently hides this error condition. Consider using a proper error mechanism or at minimum improving the error message to explain what postcondition failed.
wojpok
left a comment
There was a problem hiding this comment.
I tried to give genuine answer to question about formatting. I hope it clarifies all concerns
| assertEq (IntMap.singleton 42 True >.size) 1)); | ||
|
|
||
| testCase "randomized test" (fn _ => | ||
| testSuite "Basic tests" (fn _ => |
There was a problem hiding this comment.
This formatting needs fixing. Dont compress everything into single lines! Lines cannot exceed 80 columns in width. Try to mimic formatting style already asserted in other test files. Every test should be in separate line and it's body should be indented. Leave one empty line between individual test cases. All let definitions should start in separate lines. Pattern matching cases should be aligned to each other. Just applying that will improve readability
This is full implementation of Ordered Maps, and it is also a continuation of Pull Request #136 and #288 .