Replies: 2 comments 1 reply
-
Whoa, this decision was made three months ago, I'm trying to remember what I was my motivation. I couldn't find it so far 😁... Well, I am always revisiting how to model this in Haskell, as it is more challenging than I would do in other languages. Here, my biggest challenge is how to deal with reading objects from the disk, as Git itself is a bunch of commands for manipulating files... What I would do in an OOP language, for example, Java (sorry), is hide everything under some classes and methods, something like: abstract class Object {
private static ObjType getObjType(ByteArray raw) {
// something that parses the header of the object and return its type
}
static Object loadObject(Hash hash) {
ByteArray raw = loadRawObject(hash); // This reads the object file and uncompresses it
ObjType type = getObjType(type)
switch (type) {
case CommitType:
return Commit(raw);
break;
// same for blob and tree
}
}
class Commit extends Object {
String author;
String message;
// and so on
Commit(ByteArray raw) {
this.author = ...;
this.message = ...;
}
} Of course this is not possible in Haskell, due to the IO... So, this is the problem: I need to first read the object header to find its type, then parsing it into a internal Blob, Commit or Tree. Maybe we can replace this ObjectIO mess by specifying the types everywhere. I'll try to do that and then I'll see if it works. |
Beta Was this translation helpful? Give feedback.
-
Whoa, thanks for the class!
Whoa, indeed. I'll try to do that later. |
Beta Was this translation helpful? Give feedback.
-
Haskell's type system is robust enough for types to be inferred in almost every case, and I feel that it makes sense to have
loadObjectLegacy :: Object o => Hash -> IO o
be the standard way to load an object. The reason for that is that if the output of this action is fed into a function that is expecting, say, aCommit
, it'sobjectParse :: ByteString -> IO Commit
that will be called.However, given the
Legacy
suffix here, I imagine the functions that use the newdata ObjectIO = ObjectIO BlobIO ...
type were created out of necessity. What is the practical advantage whenloadBlob
,loadTree
andloadCommit
need to be specified? Moreover, would it not be simpler to define the type as follows?Then when someone wants to load a
Blob
given itsHash
, they can callasBlob $ loadObject hash
, and any actions that would take a generic object but for whatever reason "specialize" it can directly use these record functions:Any way we go, the question boils down to: what necessitated
ObjectIO
on top of the "legacy"loadObject :: Object o => Hash -> IO o
?Beta Was this translation helpful? Give feedback.
All reactions