This is my first program using Haskell. I'm writing it to put into practice all that I've read about FP. The first thing I'm trying to figure out is how to model the data that I'll be pulling out of my DB (eventually I'll be writing to the DB as well). I started with my users table and wrote something like this
module Model (User) where
class Audited a where
creationDate :: a -> Integer
lastUpdatedDate :: a -> Integer
creationUser :: a -> User
lastUpdatedUser :: a -> User
class Identified a where
id :: a -> Integer
data User = User {userId :: Integer}
instance Identified User where
id u = userId u
and
module Main (main) where
import Model (User)
data Point = Pt {pointx, pointy :: Float}
instance Show Point where
show (Pt x y) = "(" ++ show x ++ ", " ++ show y ++ ")"
main :: IO ()
main = do
print $ Pt 1 2
(The Point stuff is just me testing... this is my very first Haskell code ever)
This code does not compile, but I'm not really concerned about that yet -- the big thing is getting my types set up in a good way.
Here is a list of questions that I have
What is the best way to model record-based data in Haskell?
Most of my tables have audit information and opaque IDs. How can I take advantage of this using the Haskell type system? You can see that I created Audited and Identified classes. Is this a good approach?
Is this even a good application for Haskell? I was considering using Clojure as it could interoperate with Java (this application is currently written in Java).
What is the best way to model record-based data?
As an algebraic data type with possibly (Haskell) record components.
Simple example: the JSValue data type, representing JSON records.
How can I take advantage of the Haskell type system?
Interfaces in Haskell via type classes are a valid approach, though using a newtype or other data type, and not exporting its constructors provides equally strong abstraction properties. As would using an existential type or generalized algebraic data type (GADT).
Example: Look at e.g. how newtype is used in this example.
Example: newtype as used to add type safety, and abstraction, to the PCRE library.
Is this even a good application for Haskell?
Seems perfectly cromulent. Strong types, powerful FFI, and plenty of libraries on Hackage to help means you have plenty of technology to help get the job done.
Example: there are many, many database accessor libraries for Haskell, such as:
mongo
riak
berkleydb
cassandra
couchdb
tyrant
and the venerable hdbc, which is also documented in RWH.
And nice high level packages for magically persistening Haskell data.
So there's lots of choice, and plenty of examples to get started from.
Related
Since Functional Programming treats Data and Behavior separately, and behavior is not supposed to mutate the the state of an Instance, does FP recommend not having instance methods at all for Domain Objects? Or should I always declare all the fields final?
I am asking more in the context of Object oriented languages like Java.
Since Functional Programming treats Data and Behavior separately,
I heard that said a lot, but it is not necessarily true. Yes, syntactically they are different, but encapsulation is a thing in FP too. You don't really want your data structures exposed for the same reason you don't want it in OOP, you want to evolve it later. You want to add features, or optimize it. Once you gave direct access to the data you've essentially lost control of that data.
For example in haskell, there are modules, which are actually the data + behavior in a single unit. Normally the "constructors" of data (i.e. the direct access to "fields") are not available for outside functions. (There are exceptions as always.)
does FP recommends not having instance methods at all for Domain Objects
FP is a paradigm which says that software should be build using a (mathematical) composition of (mathematical) functions. That is essentially it. Now if you squint enough, you could call a method a function, with just one additional parameter this. Provided everything is immutable.
So I would say no, "FP" does not explicitly define syntax and it can be compatible with objects under certain conditions.
I am asking more in the context of Object oriented languages like Java.
This is where it kind-of gets hazy. Java is not well suited to do functional programming. Keep in mind, that it may have borrowed certain syntax from traditional FP languages, but that doesn't make it suitable for FP.
For example immutability, pure functions, function composition are all things that you should have to do FP, Java has none of those. I mean you can write code to "pretend", but you would be swimming against the tide.
does FP recommends not having instance methods at all for Domain Objects?
In the Domain Driven Design book, Eric Evans discusses modeling your domain with Entities, and Value Objects.
The Value Object pattern calls for immutable private data; once you initialize the value object, it does not change. In the language of Command Query Separation, we would say that the interface of a Value Object supports queries, but not commands.
So an instance method on a value object is very similar to a closure, with the immutable private state of the object playing the role of the captured variables.
Your fields should be final, but functional code and instance methods are not mutually exclusive.
Take a look at the BigDecimal class for example:
BigDecimal x = new BigDecimal(1);
BigDecimal y = new BigDecimal(2);
BigDecimal z = a.add(b);
x and y are immutable and the add method leaves them unchanged and creates a new BigDecimal.
I have a school project which aims to statically type some Ruby code. So, my input is simply a .rb file, and I should be able to type every variable that is assigned in the program.
Right now, what I'm planning to do is :
get the file's AST with the Parser library
put each kind of nodes in container objects
implement the visitor pattern to recursively go through the program
try to infer something from there (I was thinking of somehow creating a table of possible input and output types from the core's methods)
I only accept some very basic Ruby as input ( = no call to external library, just the core of ruby + defined-in-the-file methods)
My question is : what do you think of my approach? Is there any gem/existing programs that could help me?
Your approach is technically correct, but it sounds very strange how you put it. This:
Right now, what I'm planning to do is :
get the file's AST with the Parser library
put each kind of nodes in container objects
implement the visitor pattern to recursively go through the program
try to infer something from there (I was thinking of somehow creating a table of possible input and output types from the core's methods)
sounds a little bit like you wanted to go to Mars like this:
Right now, what I'm planning to do is :
get a pencil
get a piece of paper
get a desk
sit down at the desk and use my pen and paper to design a space launch system and Mars lander
In other words, you list three completely trivial points that are maybe an hour of work for an experienced programmer, and then a fourth, that is multiple years of work and worth a PhD.
The most advanced work I know regarding static type inference for Ruby was Diamondback Ruby (DRuby) (not to be confused with the Distributed Ruby standard library aka dRb / dRuby). However, Diamondback Ruby is now abandoned, since the authors gave up on static type inference for Ruby.
One of the principal researchers behind Diamondback Ruby is now working on a new project called RDL. The main differences between Diamondback Ruby and RDL are:
RDL performs dynamic checking, not static checking
RDL relies on explicit annotations, not implicit inference
Steep is another similar project. It, too, relies on dynamic checking and annotations, and in addition does not actually strive for type-correctness.
Ruby Type Inference for IDEA is a complete re-think of how JetBrains plans to approach type inference for Ruby in their IDEA / RubyMine IDE. This does use type inference, but it uses dynamic type inference, not static.
So, as you can see, static type inference for Ruby is so hard that nobody is even trying it, and the guys who did try gave up on it and are now doing dynamic type checking with explicit type annotations instead.
Ruby Type Checking Roundup on Robert Mosolgo's blog is a good overview about the current state-of-the-art in Ruby typing.
I am learning Ruby and I'm having a major conceptual problem concerning typing. Allow me to detail why I don't understand with paradigm.
Say I am method chaining for concise code as you do in Ruby. I have to precisely know what the return type of each method call in the chain, otherwise I can't know what methods are available on the next link. Do I have to check the method documentation every time?? I'm running into this constantly running tutorial exercises. It seems I'm stuck with a process of reference, infer, run, fail, fix, repeat to get code running rather then knowing precisely what I'm working with during coding. This flies in the face of Ruby's promise of intuitiveness.
Say I am using a third party library, once again I need to know what types are allow to pass on the parameters otherwise I get a failure. I can look at the code but there may or may not be any comments or declaration of what type the method is expecting. I understand you code based on methods are available on an object, not the type. But then I have to be sure whatever I pass as a parameter has all the methods the library is expect, so I still have to do type checking. Do I have to hope and pray everything is documented properly on an interface so I know if I'm expected to give a string, a hash, a class, etc.
If I look at the source of a method I can get a list of methods being called and infer the type expected, but I have to perform analysis.
Ruby and duck typing: design by contract impossible?
The discussions in the preceding stackoverflow question don't really answer anything other than "there are processes you have to follow" and those processes don't seem to be standard, everyone has a different opinion on what process to follow, and the language has zero enforcement. Method Validation? Test-Driven Design? Documented API? Strict Method Naming Conventions? What's the standard and who dictates it? What do I follow? Would these guidelines solve this concern https://stackoverflow.com/questions/616037/ruby-coding-style-guidelines? Is there editors that help?
Conceptually I don't get the advantage either. You need to know what methods are needed for any method called, so regardless you are typing when you code anything. You just aren't informing the language or anyone else explicitly, unless you decide to document it. Then you are stuck doing all type checking at runtime instead of during coding. I've done PHP and Python programming and I don't understand it there either.
What am I missing or not understanding? Please help me understand this paradigm.
This is not a Ruby specific problem, it's the same for all dynamically typed languages.
Usually there are no guidelines for how to document this either (and most of the time not really possible). See for instance map in the ruby documentation
map { |item| block } → new_ary
map → Enumerator
What is item, block and new_ary here and how are they related? There's no way to tell unless you know the implementation or can infer it from the name of the function somehow. Specifying the type is also hard since new_ary depends on what block returns, which in turn depends on the type of item, which could be different for each element in the Array.
A lot of times you also stumble across documentation that says that an argument is of type Object, Which again tells you nothing since everything is an Object.
OCaml has a solution for this, it supports structural typing so a function that needs an object with a property foo that's a String will be inferred to be { foo : String } instead of a concrete type. But OCaml is still statically typed.
Worth noting is that this can be a problem in statically typed lanugages too. Scala has very generic methods on collections which leads to type signatures like ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Array[T], B, That]): That for appending two collections.
So most of the time, you will just have to learn this by heart in dynamically typed languages, and perhaps help improve the documentation of libraries you are using.
And this is why I prefer static typing ;)
Edit One thing that might make sense is to do what Scala also does. It doesn't actually show you that type signature for ++ by default, instead it shows ++[B](that: GenTraversableOnce[B]): Array[B] which is not as generic, but probably covers most of the use cases. So for Ruby's map it could have a monomorphic type signature like Array<a> -> (a -> b) -> Array<b>. It's only correct for the cases where the list only contains values of one type and the block only returns elements of one other type, but it's much easier to understand and gives a good overview of what the function does.
Yes, you seem to misunderstand the concept. It's not a replacement for static type checking. It's just different. For example, if you convert objects to json (for rendering them to client), you don't care about actual type of the object, as long as it has #to_json method. In Java, you'd have to create IJsonable interface. In ruby no overhead is needed.
As for knowing what to pass where and what returns what: memorize this or consult docs each time. We all do that.
Just another day, I've seen rails programmer with 6+ years of experience complain on twitter that he can't memorize order of parameters to alias_method: does new name go first or last?
This flies in the face of Ruby's promise of intuitiveness.
Not really. Maybe it's just badly written library. In core ruby everything is quite intuitive, I dare say.
Statically typed languages with their powerful IDEs have a small advantage here, because they can show you documentation right here, very quickly. This is still accessing documentation, though. Only quicker.
Consider that the design choices of strongly typed languages (C++,Java,C#,et al) enforce strict declarations of type passed to methods, and type returned by methods. This is because these languages were designed to validate that arguments are correct (and since these languages are compiled, this work can be done at compile time). But some questions can only be answered at run time, and C++ for example has the RTTI (Run Time Type Interpreter) to examine and enforce type guarantees. But as the developer, you are guided by syntax, semantics and the compiler to produce code that follows these type constraints.
Ruby gives you flexibility to take dynamic argument types, and return dynamic types. This freedom enables you to write more generic code (read Stepanov on the STL and generic programming), and gives you a rich set of introspection methods (is_a?, instance_of?, respond_to?, kind_of?, is_array?, et al) which you can use dynamically. Ruby enables you to write generic methods, but you can also explicity enforce design by contract, and process failure of contract by means chosen.
Yes, you will need to use care when chaining methods together, but learning Ruby is not just a few new keywords. Ruby supports multiple paradigms; you can write procedural, object oriend, generic, and functional programs. The cycle you are in right now will improve quickly as you learn about Ruby.
Perhaps your concern stems from a bias towards strongly typed languages (C++, Java, C#, et al). Duck typing is a different approach. You think differently. Duck typing means that if an object looks like a , behaves like a , then it is a . Everything (almost) is an Object in Ruby, so everything is polymorphic.
Consider templates (C++ has them, C# has them, Java is getting them, C has macros). You build an algorithm, and then have the compiler generate instances for your chosen types. You aren't doing design by contract with generics, but when you recognize their power, you write less code, and produce more.
Some of your other concerns,
third party libraries (gems) are not as hard to use as you fear
Documented API? See Rdoc and http://www.ruby-doc.org/
Rdoc documentation is (usually) provided for libraries
coding guidelines - look at the source for a couple of simple gems for starters
naming conventions - snake case and camel case are both popular
Suggestion - approach an online tutorial with an open mind, do the tutorial (http://rubymonk.com/learning/books/ is good), and you will have more focused questions.
I'm trying to do use the science.plt module in a typed racket program, but I'm having a hard time understanding how to use the require/typed form properly. I've read the docs repeatedly, but I guess I don't quite understand what exactly I'm trying to produce with the form.
In the
[struct name ([f : t] ...)]
form, is the name a name I should expect to find in the module I want to require, or am I making it up for use within my own program?
Probably the most helpful thing for me would be an example or three of require/typed applied to untyped racket modules.
Or if I'm misunderstanding this real deeply and one cannot use untyped modules in a typed program, how should I go about structuring things? I really just need the random number and random distribution functionality from the science.plt module, and don't expect to have any other imports, at this point.
Did you have a look at the Typed Racket reference page for require/typed? There are several examples there showing how to import from untyped modules.
The name expression in the [#:struct name ([f : t] ...) struct-option ...] clause is supposed to be the name of a structure type.
That is, if you have a struct like (struct point (x y), the name is supposed to be point.
I am developing a complex data structure in Clojure with multiple sub-structures.
I know that I will want to extend this structure over time, and may at times want to change the internal structure without breaking different users of the data structure (for example I may want to change a vector into a hashmap, add some kind of indexing structure for performance reasons, or incorporate a Java type)
My current thinking is:
Define a protocol for the overall structure with various accessor methods
Create a mini-library of functions that navigate the data structure e.g. (query-substructure-abc param1 param2)
Implement the data structure using defrecord or deftype, with the protocol methods defined to use the mini-library
I think this will work, though I'm worried it is starting to look like rather a lot of "glue" code. Also it probably also reflects my greater familiarity with object-oriented approaches.
What is the recommended way to do this in Clojure?
I think that deftype might be the way to go, however I'd take a pass on the accessor methods. Instead, look into clojure.lang.ILookup and clojure.lang.Associative; these are interfaces which, if you implement them for your type, will let you use get / get-in and assoc / assoc-in, making for a far more versatile solution (not only will you be able to change the underlying implementation, but perhaps also to use functions built on top of Clojure's standard collections library to manipulate your structures).
A couple of things to note:
You should probably start with defrecord, using get, assoc & Co. with the standard defrecord implementations of ILookup, Associative, IPersistentMap and java.util.Map. You might be able to go a pretty long way with it.
If/when these are no longer enough, have a look at the sources for emit-defrecord (a private function defined in core_deftype.clj in Clojure's sources). It's pretty complex, but it will give you an idea of what you may need to implement.
Neither deftype nor defrecord currently define any factory functions for you, but you should probably do it yourself. Sanity checking goes inside those functions (and/or the corresponding tests).
The more conceptually complex operations are of course a perfect fit for protocol functions built on the foundation of get & Co.
Oh, and have a look at gvec.clj in Clojure's sources for an example of what some serious data structure code written using deftype might look like. The complexity here is of a different kind from what you describe in the question, but still, it's one of the few examples of custom data structure programming in Clojure currently available for public consumption (and it is of course excellent quality code).
Of course this is just what my intuition tells me at this time. I'm not sure that there is much in the way of established idioms at this stage, what with deftype not actually having been released and all. :-)