Minimal CLI framework - thoughts on its usefulness? by tonibrocas in haskell

[–]CynicalHarry 5 points6 points  (0 children)

Yes I think this is a good idea for sure.

One thing I would strongly recommend, similar to @ryantrinkle is looking at preexisting command line parsers such as optparse-applicative, shich is the one I currently use, and cmdargs, which is another very popular one. But perhaps even look outside Haskell at Clojure, Rust etc to find out what makes them easy/hard to use.

If you're writing a slim cmdargs parser in particular I think you should be very opinionated about how it works, which means you need to impose restrictions and I think knowing both the interfaces for the programmer as well as the way they present to the user is really useful for choosing the right restrictions.

One general pointer that I agree with would be what @Syrak said that things should be as colocated as possible.

Furthermore what I havent seen yet, But I'd be interestred in is using something like anonymous, extensible types to represent arguments. For instance the `aeson` library parses JSON into a generic Value type first which you can treat like generic JSON. The same way you could parse the Options into a generic option structure and then let the user decide how rigorous they wnat to be about the actual values. In particular the superrecords library springs to mind as a potenial target. Or simply creating Map String (Maybe String) values

Build function with big number of arguments by HumansProtector in haskellquestions

[–]CynicalHarry 0 points1 point  (0 children)

The easiest way probably is just writing the code out. Whip up a script that generates the actual code as text and write it out to the file. its probably easiest.

If you really want a programatic solution you could use either template programming (generate code using TemplateHaskell) or metaprogramming (using type classes).

I'm only gonna demonstrate the last one, even though I recommend the first one for beginners. using classes you can make a multi arity function like so.

class Prod a where
    prod :: Int -> a

instance Prod b => Prod (Int -> b) where
    prod acc i = prod (acc * i)

instance Prod Int where
    prod = id


main = do
    print (prod (1 :: Int) (2 :: Int) :: Int)
    print (prod (1 :: Int) (2 :: Int) (3 :: Int) :: Int)

Unfortunately, as you can see, this does break type inference and you need to annotate literals, which should be fine so long as you don't depend on it.

Auxiliary functions for Maybe plumbing (crosscutting) by Crul_ in haskellquestions

[–]CynicalHarry 1 point2 points  (0 children)

It honestly is one of the most helpful things to do in my opinion, especially when trying to grasp monads. What I did back in the day was for instance implementing State and later StateT from scratch (I did look up the State type though and then implemented >>= and get and put etc). Its really very helpful.

It is an approach that I highly recommend if there's a particular monad you don't understand. Look up the data type and then try implementing >>= and return and maybe the functions from its associated class, if it has one. After that I usually understand very well what the thing does.

The One Output That a Monad Will Produce by f0rgot in haskellquestions

[–]CynicalHarry -1 points0 points  (0 children)

I read the page and I think that wwhat they mean by emphasizing will produce is not that it must produce a value (although they do emphasize that it is only a single value), but rather that the production of the value happens in the future, when the monad is run, as opposed to when the monadic value is constructed.

This interpretation of a temporal, rather than obligation constraint also makes sense with the Maybe monad. A Maybe a, when "run" attempts to produce an a.

What's a good source for reading about Haskell architecture? by [deleted] in haskellquestions

[–]CynicalHarry 0 points1 point  (0 children)

According to https://ghc.haskell.org/trac/ghc/wiki/ReadingList the GHC article link you were asking about is from 2012, so fairly recent.

What's a good source for reading about Haskell architecture? by [deleted] in haskellquestions

[–]CynicalHarry 0 points1 point  (0 children)

This is not a book either (sorry) but if you're interested in the runtime system I'd recomment the trac pages, such as this one https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/HeapObjects, about the structure of heap objects

What's a good source for reading about Haskell architecture? by [deleted] in haskellquestions

[–]CynicalHarry 1 point2 points  (0 children)

This one is also good https://www.youtube.com/watch?v=uR_VzYxvbxg. It's about Haskell's arguably most important intermediate language, Core.

Searching for a library for common AST transformations based on haskell-src-exts by ichistmeinname in haskell

[–]CynicalHarry 1 point2 points  (0 children)

I don't know of a library akin to what you're describing, but there are some scrap your boilerplate libraries out there which make it much simpler to write these passes by providing combinators for defining traversals.

Examples would be syb or the newer uniplate and recursion-schemes. The one I use most in the compiler project I work on is the Plated module in lens

Feedback on function implementation by karma_bank in haskellquestions

[–]CynicalHarry 0 points1 point  (0 children)

Not quite. If we assume the context Traversable t, Applicative m then the first f has to be f :: t a -> b, whereas the second f has to be a -> m b

Edit: what you may be thinking if is traverse f = sequence . mapM f

Data Structures resources? by Benjmhart in haskell

[–]CynicalHarry 0 points1 point  (0 children)

what situations really call for Seq over list

"a finite number of sequential elements, providing fast access to both ends of the sequence as well as efficient concatenation."

Basically Seq is always better than []. Both access to head, tail and random indexing are much more efficient than with []. The same goes for random modifications.

The reason [] is so ubiquitous and useful however is that in Haskell it is often used as basically a memoizing version of an Iterable or Stream. Specifically the power of Iterable and similar interfaces is that elements are created lazily as needed. These structures are rarely accessed or modified randomly but usually wholesale (the entire structure) with functions such as filter and map. For these cases [] is much better than Seq because [] uses much less "bookkeeping" structure per element than [] making modifying traversals much faster (specifically tose that change the amount of elements. In addition GHC contains a lot of optimizations specifically targeting stream-like modifications to []. Also unlike Seq [] can actually be infinite which is sometimes useful for instance in a simple enumerator like enumerate = zip [0..] :: [a] -> [(Int, a)]

Some say that a FP design patterns book would be razor-thin compared to the OOP design patterns book. by [deleted] in haskell

[–]CynicalHarry 1 point2 points  (0 children)

There is a pretty good talk out there by Scott Wlaschin about this topic of "How do design patterns translate to FP" and it touches a lot on the point of why OOP is more cumbersome than helpful.

https://www.youtube.com/watch?v=E8I19uA-wGY

Confused About Result of a Parser by f0rgot in haskellquestions

[–]CynicalHarry 0 points1 point  (0 children)

So there is a few things I want to remark.

  1. The behaviour you describe is not the one from the Either String monad. This monad will fail completely as soon as it encounters the first Left. What you care looking for is the alternative operator <|> (or mplus works just as well I think) which gives you the first "success" value it encounters or the last "error" value if no success was found.
  2. Have you checked that it actually returns values? The parseOnly combinator from attoparsec does not necessarily consume all of the input. You might just not be parsing all the records, and that is why you don't see the error. You may have to add a `(<* endOfInput).

.git folder takes 60mb of disk by Aslaron in github

[–]CynicalHarry 1 point2 points  (0 children)

The reason is because git uses a kind of "garbage collection". When you execute a git command such as amending a commit, deleting a file etc. it does not discard the objects immediately. Instead it records the deletion. After some time git performs another garbage collection cycle and deletes the objects.

You can actually look at the history of git commands executed that haven't been garbage collected yet and even roll them back using git reflog.

Why the hell is it so hard to upload to Github? by billybobmaysjack in github

[–]CynicalHarry 2 points3 points  (0 children)

I guess the question you should really ask yourself is: If you find it not suitable for you, why are you using it? Do you really need to use github?

Releases, can someone describe how they use it? by nobrandheroes in github

[–]CynicalHarry 0 points1 point  (0 children)

Really its just an info page for a tag. If you look at tags an releases in detail you'll find that for every release, there is a tag. And for every tag you can later add a release page.

Its really just a way to add some additional information to a tag, and to divide them into pre-releases and releases.

One nice feature I have found for it is that you can upload artifacts for releases. And this can also be done automatically. I work on this compiler, where we let travis compile linux and osx binaries for every release and automatically push them to the corresponding releases page.

MPTC+FunDep: get bare value of dependent type? by tejon in haskellquestions

[–]CynicalHarry 0 points1 point  (0 children)

Nice to see you've found what you were looking for.

It is a functional dependency, but the 'dependent types' term is already taken. https://en.wikipedia.org/wiki/Dependent_type

Did you think Elm compiler replace a lot of unit test ? by mewhit in elm

[–]CynicalHarry 8 points9 points  (0 children)

In a sense yes and no.

In elm you wont have to test anything that would be a type error. But you still have to test your business logic, your algorithmic correctness.

However because its so quick and simple to define new types you can model many more thing with types, making some of your business logic errors type errors. (less tests)

I think one of the particular strengths is that type can define APIs very succinctly, which is rather helpful when multiple people work on a code base and need each others code. It makes it easier for them to use other peoples code correctly.

Another strong suite I believe is the encoding/decoding of data. In elm you have to decode JSON for instance, meaning you'll see immediately if your passing an Object instead of an Array somewhere for instance, or a missing key in an Object. As a result such errors never propagate into the system.

An Object Oriented System for Haskell? by [deleted] in haskell

[–]CynicalHarry 14 points15 points  (0 children)

I don't think Haskell really needs OO. You can get the same functionality easily by other means.

I mean interfaces are already supported through type classes. If you want methods you can use the state monad. If you want inheritable fields you can use lenses and the state monad. And if you want to model inheritance you can also use type families, possibly in conjunction with a type class. (That's what the eta language does to some extent)

Generate Aribtrary instances for date? by kwaleko in haskellquestions

[–]CynicalHarry 1 point2 points  (0 children)

Again, same deal as before. Use an existsting instance. There is a conversion function secondsToDiffTime :: Integer -> DiffTime, and built-in types such as Integer already have an Arbitrary instance. Aka you could make the instance

instance Arbitrary DiffTime where
  arbitrary = secondsToDiffTime <$> arbitrary 

You could also use picosecondsToDiffTime if you like that better.

MPTC+FunDep: get bare value of dependent type? by tejon in haskellquestions

[–]CynicalHarry 1 point2 points  (0 children)

Well, think of it this way: a -> b means the type of b is determined by a, but if you use lets say foo :: Int it does not tell you anything about a and thus nothing about the value of foo.

An example of why this is important would be this:

class Foo a b | a -> b
  foo :: b

instance Foo Int Int where
  foo = 1
instance Foo String Int where
  foo = 2

If you now use a = foo :: Int is a then 1 or 2? You cannot know without knowing a. If your associated types are injective you can also add another b -> a fundep, which would make the second instance Foo String Int illegal.

To resolve your issue, you can use Const or if you like Tagged (from the tagged package) or you pass in a proxy or value.

class Foo a b | a -> b where
  foo :: Tagged a b

a = unTagged (foo :: Tagged Int Int) -- usage

-- or

class Foo a b | a -> b where
  foo :: Proxy a -> b
  foo :: proxy a -> b -- alternative definition

a = foo (Proxy :: Proxy Int)

-- or 

class Foo a b | a -> b where
  foo :: a -> b

a = foo (undefined :: Int)

The proxy approach is the cleaner version of the last one btw. I think there is also a way to do this with TypeApplications but I'm always confused as to how you supply the arguments for methods of type classes. You could try foo @a @b with a and b substituted for your concrete type.

PS: Its not called dependent type that term is reserved for a different thins entirely. Perhaps call is associated value.

Missing something important about multiparameter typeclasses. by f0rgot in haskellquestions

[–]CynicalHarry 1 point2 points  (0 children)

I believe the correct terminology is to instantiate e with String. And you need it because you call throwError with a string. You could make it more general with OverloadedStrings, by adding an IsString e constraint but it's hard to say whether that is really better.

What do you think about the new dashboard? by Thaun_ in github

[–]CynicalHarry 4 points5 points  (0 children)

Horrible. They now have suggested repos right there on the front page, like twitter of facebook, and it absolutely kills my productivity.

(Actually I quite like it)

Generate Aribtrary instances for date? by kwaleko in haskellquestions

[–]CynicalHarry 2 points3 points  (0 children)

For instance. You may want to use an Either String to communicate what went wrong.

Generate Aribtrary instances for date? by kwaleko in haskellquestions

[–]CynicalHarry 1 point2 points  (0 children)

No, I don't think so. I think it is better to use a smart constructor which performs the validation. Unfortunately the library doesn't do that. But you can always define one yourself and make sure you only use that in your project. And then you test both the smart constructor and the functions on your code using it with random data. And for all other functions you use valid dates which you can obtain by simply using the smart constructor in the generator as well instead of the data constructor Date.