My first language was Racket and so naturally I gravitated to the lispy untyped functional programming style even when I was using languages like Python or Java, but when I tried Haskell for the first time my mind was absolutely blown and I was a convert ever since. What are your thoughts?
Nowadays, I definitely prefer typed. There was a time I really liked untyped (e.g. Lisp), because I felt so much freedom compared to the (rather simple) typed languages I had used. Then I learned Haskell and found out that types were not the problem, but that the type systems I had used until then were simply not expressive enough for what I wanted to do.
Exactly the same here. 10+ years ago, untyped languages felt so much more productive; they were a breath of fresh air compared to e.g. Java. But after discovering typed languages with type inferencing (Haskell) and nowadays gradually typed languages, I cannot work without types anymore. It feels icky to not have a compiler check types.
I like the typing system of OCaml but I also like the fact that typing systems are optional in the lisps (Typed Racket, Typed Clojure, the CLOS…)
I like statically typed languages more than untyped, however the more I get into strict typing it just seems like compile time predicates/asserts. which is something you can use in a lot of languages to get strict typing. I mainly use Common Lisp and it has several things built in like DEFTYPE and you can create predicates to specify a type. though obviously not mandatory it can be quite nice. so I guess at the moment I am more in the middle I use types when they seem useful and dont when I am in a hurry or they are not needed.
If the language has really good type inference (Haskell comes to my mind though F# was quite nice as well) it’s better. It really makes life much easier.
However when dealing with real-world problems (just moving data around which are changing constantly) the types don’t really add that much, you need to test anyway. Test suites is what I need. Clojure and Common Lisp are OK.
I agree. F# has also type providers (https://learn.microsoft.com/en-us/dotnet/fsharp/tutorials/type-providers/) that are a form of type-inference on steroids, for assigning types to external resources.
IMHO, whenever possible it is better using static typing, but there are real world problems where the nature of data is extremely dynamic, or the types are very complex. In these cases a naive but rigid static type system can be a problem. So in these cases it is better or a relaxed static type system where some constraints can be checked at run-time (i.e. like a dynamic type-system), or a very powerful static type system. In a certain sense, Common Lisp and Racket are examples of the first case, because you can add type annotations to code, so they are both dynamically and statically typed language.
My main functional programming is Scala, which I absolutely love as a programming language. Due to it’s simple implicits feature it feels a light as weak-typing but with the guarantees and debuggability of strong types. The types are there but the RSI isn’t! However my experience is limited.
I also started my FP journey with untyped languages. Finding Haskell changed my perspective because it answered questions I hadn’t yet been able to clearly articulate to myself.
That said, I do sympathize with the criticism that static types can make some things harder to use. I think it’s because we’re not yet doing everything right, but the reality is that some, say, Python APIs are faster to get going with than comparable things in Haskell.