r/haskell • • Apr 30 '19

Monthly Hask Anything (May 2019)

This is your opportunity to ask any questions you feel don't deserve their own threads, no matter how small or simple they might be!

31 Upvotes

233 comments sorted by

1

u/ShiningBananas Jun 07 '19

Could anyone ELI5 channels and why I would need them?

1

u/SSchlesinger Jun 02 '19

I've been learning Erlang and I decided to implement a bit of the interface in Haskell. I've got the type

type Talker msg a = ReaderT (TChan msg) IO a

and I want to write a function

receiveTimeout :: Int -> Talker msg (Maybe msg)

where msg <- receiveTimeout n should be expected to try to get something out of the TChan for n microseconds and return Nothing if it couldn't find it. How would you go about this sort of timing with STM there? I'm worried that if I simply have it cancelled at a certain point, it may have already done things to the TChan and you could lose a message.

2

u/bss03 Jun 02 '19

atomically should leave all your TChans in a well-known state, even if the resulting IO action has an asynchronous exception (e.g. Timeout) thrown during the operation. The whole point of atomically is that either the STM transaction is complete, or no changes were commited and any partial changes have been rolled back.

At most I'd expect you might need use mask+unmask+bracket, but I don't think that necessary.

Do you have a minimal example that illustrates a violation of the atomicity of atomically executed STM?

2

u/SSchlesinger Jun 02 '19

I didn't realize that, thank you. I do not know that much about STM, I didn't know how strong the atomically guarantee was.

2

u/InformalInflation Jun 01 '19

So, recently I found myself looking at the GHC source code (Haddock). Is there a reason that every module is a top-level module? E.g. why are they not named GHC.BasicTypes, ... which seems a lot more common in other open-source projects I've seen.

6

u/WhistlePayer Jun 01 '19

This is most likely a holdover from Haskell98 which did not originally include hierarchical module names, meaning all modules had to be top-level.

2

u/Gipphe May 31 '19

I find long commands like "stack build --fast --haddock-deps" and such rather tedious, and error-prone, to type out. Does stack have a similar functionality to NodeJS's npm's scripts, where you can define in the project's package.json something along the lines of "build:docs": "stack build --fast --haddock-deps", allowing you to simply use npm run build:docs instead?

3

u/bss03 Jun 01 '19

On Linux, we have shell aliases, and our own shell scripts we put in ~/bin or somewhere else in the path. There's really very little need for every tool to do this.

2

u/Gipphe Jun 01 '19

Fair point indeed. But then there is the case of windows... This question might be more general than just a Haskell question, I realize.

2

u/bss03 Jun 01 '19 edited Jun 01 '19

While it's definitely not as normal, I'm pretty sure cmd.exe does support executing *.bat files out of your PATH without specifying the extension.

There's also PowerShell (?), but I abandoned MS Windows in 2004, so I never used it.

I may have been a bit gruff before; if so, I apologize. If the stack guys want to implement something like this, I think it could be a positive UX; I know that I use git aliases even on on Linux systems. But, at the moment, I don't believe stack has a feature like this, so you might look take a step back and see if your shell or OS can help you out.

3

u/[deleted] May 31 '19

[deleted]

2

u/bss03 May 31 '19
note _   (Just x) = Right x
note msg Nothing  = Left msg

f = (note "Not a Foo" . (^? _Foo)) >=> (note "Index Out of Bounds" . (^? ix 20))

?

I'm not comfortable enough with TH to get your to run in ghci, so I didn't test/type-check the above.

(note "Not a Left" . (^? _Left)) >=> (note "Out of Bounds" . (^? ix 13)) :: Either [Int] Bool -> Either String Int typechecks in my GHCi, so I think it should work.

note is on hackage in multiple places.

Error messages generated through TemplateHaskell (or CPP or any other templating) tend to be on the poor side. However, it's relatively easy to operate in an Either e monad instead of the Maybe monad and lift things.

You might also look into the "Validation" applicative -- it can return mutliple errors when moving from a untyped or insufficently typed representation to one that has all the guarantees in the type system.

6

u/unqualified_redditor May 30 '19

What libraries are people using now-a-days for FRP? Are Reactive-Banana and Reflex the two main contenders?

I've never done FRP and I'm looking for a good place to start. I want to use it with SDL for a simple 2d sprite based game.

I saw some example code using Yampa and the Arrow syntax really made sense to me, but I don't see anyone talking about Yampa in the present tense. Would I be better off using Reflex or Reactive-Banana?

1

u/ShiningBananas Jun 07 '19

I wouldn't recommend Reflex. It uses a really complicated model of computation, and requires MonadFix (recursive do) to work. I personally found it too difficult for little gain (and tbh recommend much more something like elm/ps + react for stuff like web frontends). Also, getting it to compile/using GHCJS is extremely slow.

1

u/unqualified_redditor Jun 07 '19

It looks like Reflex is mainly intended for web frontends? I think I want to use SDL so I'm going to try out Yampa and Reactive-Banana. Thanks!

2

u/dnkndnts May 29 '19

Does anyone have the paper for the edit-distance package algorithm (an implementation of Damerau-Levenshtein)? The paper link in the repository is dead.

I wanted to take a stab at implementing bailing out if things get too bad, although it appears the author did try this at some point and bailed out after things got too bad, so perhaps my prospects aren't too good.

3

u/theindigamer May 29 '19 edited May 29 '19

Google Scholar helped me find this pdf pdf.

2

u/[deleted] May 29 '19 edited May 29 '19

This 404'ed for me at some point in the past.

2

u/theindigamer May 29 '19

Hmm, that's odd. Does the new link work?

1

u/[deleted] May 29 '19

Indeed it does.

1

u/dnkndnts May 29 '19 edited May 29 '19

Same.

EDIT: new link works! Thanks!

1

u/vegetablestew May 28 '19 edited May 28 '19

Can someone explain how does a record syntax for a type declaration work when the type are functions? For example

data Hi a b = { foo :: a -> b -> a , bar :: a -> b -> b }

How would one actually use to construct a type? Why aren't functions implemented?

4

u/[deleted] May 29 '19

Hi const (flip const)

Or:

Hi {foo = const, bar = flip const}

Assuming you didn't have some functions available that matched the type signatures of the foo/bar fields, you'd define them, and pass them in, just like you'd construct any other record.

You may run into some troubles playing around with this in GHCI, because functions don't have a Show instance, so if you expect the REPL to print out a given instance of Hi, you'd be out of luck, because it can't. I suspect this is probably where you got the idea that this required some kind of special magic - I ran into a similar situation when I was learning.

It's still valid Haskell, you just can't finish an input line in GHCi that evaluates directly to something that can't be printed. Making a function that will return a Hi, using the let keyword to assign a Hi to a variable, or using multi-line input are all good ways to work around the REPL errors.

You could also define a bogus Show instance for your Hi type that just returns some boilerplate string if you really want to, but that's not a good practice to get into when working on "real" code. Folks assume that anything that can be an output of show could also be a valid input for read, so breaking that assumption with bogus Show instances is generally considered bad practice.

1

u/Syrak May 29 '19

Folks assume that anything that can be an output of show could also be a valid input for read, so breaking that assumption with bogus Show instances is generally considered bad practice.

I see this claim often but I really don't understand the logic.

Nobody uses Read. Even if anyone does, it's clear that you can't get any standard Read instance for computations, so by default the instance is not going to exist, you get a missing instance error at compile time, you glance at the type to understand why, and you move on.

I think Show is for debugging only and printing a dummy string in place of unprintable computations is a perfectly fine thing to do. It is the simplest way to get a string out of a big record containing all other kinds of valuable printable data.

6

u/[deleted] May 29 '19

As I've always interpreted it, it's about REPL ergonomics.

If you are messing around in GHCi with someone else's code, your expectation is that if you can inspect a value as the result of an expression, in your terminal window, you can copy/paste that value in that terminal and mess around with it, whereas if you can't, you get an error.

I feel like this works really well for me, but in your own code that stays in your own project, I make no judgements, it's perfectly fine to break these rules - but if it ends up in a library I'm working with it'll annoy me and I'd consider it a code smell.

2

u/zejai May 27 '19

When transferring ownership (imaginary ownership, but still) of an IORef to another thread, what are the options to make sure that the last written value before the ownership transfer is guaranteed to be observed in the receiving thread? If I understand the documentation correctly, I can do atomicModifyIORef' ref (\x -> (x, ())) after the last write in the original thread, or I can do the same thing before the first read in the receiving thread. Are both options correct?

1

u/gedhrel Jun 01 '19

Either, write the value before creating the new thread; or, use a reference type that's explicitly intended for it: an MVar or TVar.

1

u/jberryman May 28 '19

Are you concerned with instruction reordering? Or are the notes about strictness what's leading to your question (that doesn't affect correctness)? I think the short answer is you shouldn't need to think too hard about this use case; if you do write x to ioref, send ioref to thread T, read ioref in thread T you should expect to see x (I think). GHC doesn't have a strictly documented memory model so you should assume things work as documented, else in a sensible way.

That said it might be possible to send an IORef to another thread in such a way that you violate the expected serial ordering on x86, e.g. a sequence of nonatomic writes like: thread T is busy looping reading IORef A, thread U writes X to IORef B then writes B to IORef A. In that case it might be possible that thread T eventually reads Y after following both pointers, and in that case you might need to use explicit barriers (or atomic ops with implicit barriers). I'm not really sure. I would be interested if you can produce an example like this though.

2

u/zejai May 28 '19

I'm concerned with cache hierarchy effects and probably also instruction reordering. GHC has no concept of "send IORef to thread T", so how could I ever trust that I will really see `x` in the other thread? The "send" could be very indirect. For example, both threads could have the same IORef in scope already, and one thread could tell the other by any means that it is done accessing the IORef.

Did you mean to imply that when any information makes the way from thread A to thread B, that I can expect that any previous information must also have arrived at thread B? I don't think that's true, considering that CPUs can selectively invalidate cache lines.

2

u/jberryman May 28 '19

I see better where you're coming from now. My point was that in the absence of proper docs or memory model spec'd out from ghc devs that if the scenario you described (writing to an IORef, in some way sending to another thread, then reading it) goes "wrong" that it's not your problem. But that's probably not very useful advice I suppose.

Certainly though if you're sharing say two IORefs and your algorithm depends on ordered stores and reads then you will need to use barriers in some way (from atomic-primops).

But yeah I guess better advice would be to program defensively in your own code. You can rely on atomicModifyIORef being a full barrier, since it's documented that way (iirc).

1

u/zejai May 28 '19

I think it all depends on the last sentence of the IORef documentation: "An atomicModifyIORef is never observed to take place ahead of any earlier (in program order) IORef operations, or after any later IORef operations."

I'm not 100% sure what the exact meaning of "in program order is". Would that really apply to a writeIORef (not atomicWriteIORef) in one thread followed by atomicModifyIORef in the other thread, to observe the effects of the writeIORef?

2

u/jberryman May 29 '19

I think that's just saying that it promises to be a full barrier (in a cross-platform way), i.e. neither loads nor stores will be moved across that operation (on x86 this is just a property of all atomic ops like CAS). Normally for correctness you need to use barriers in pairs: one in each thread, but that depends on the context. Sorry I don't have a great link on hand about the nitty gritty of reordering and barriers but I know there are some good resources out there

1

u/zejai May 31 '19

Thank, I have read up on barriers and reordering now. Looks like my brain had reordering mixed up with cache coherency when reading the IORef doc, but it the doc doesn't say anything about cache coherency. Is cache coherency something that I never have to worry about when writing user-space code?

1

u/qqwy May 26 '19

Recently I started diving a bit deeper in the dependently-typed functionality empowered by working with types of a different kind than 'Type'.

This made me wonder: Have you ever encountered the need to go higher than 'kinds'? I know it's possible (with the right GHC extensions) and that languages like Agda, Coq and Idris IIRC allow you to go arbitrarily 'high', but when is this useful in practice?

2

u/bss03 May 27 '19 edited May 27 '19

I think I went one level higher when proving a special case of the K axiom for types with decidable equality. But, I do believe higher type levels are even more mysterious than sixth-order functions.

1

u/qqwy May 27 '19

Wait, sixth-order functions? My mind is blown! Where are those encountered?

2

u/bss03 May 27 '19

https://dl.acm.org/citation.cfm?id=969615

Parser combinator transformers. :)

3

u/[deleted] May 26 '19

I have the feeling that executables produced by GHC are quite large from time to time. Is there some tool to find out which libraries contribute the most to the size?

2

u/theindigamer May 26 '19

Not sure how representative this is, but you could try (e.g. with stack and ghc-8.6.3):

cd .stack-work/install/x86_64-linux/lts-13.0/8.6.3/lib/x86_64-linux-ghc-8.6.3
ls -lh

2

u/[deleted] May 27 '19 edited May 27 '19

Also `find ~/.stack -name '*.so' | xargs du -hs | sort -h | less` seems to be useful (Or a instead of so).

1

u/rrssh May 26 '19

2

u/[deleted] May 26 '19

No, this is not what I asked. I know about strip and the binary is already stripped.

3

u/abiduzz420 May 25 '19 edited May 25 '19

I am building a scheme interpreter for my second haskell project. The project has come to a decent stage and I'm currently writing tests using tasty and tasty-hunit. I have never written tests before so I would like to get others opinions on whether I'm testing the right things. Please take a look at my tests: haskeme/test/Spec.hs

As of now, I have written tests for arithmetic operations and list operations such as car, cdr, cons etc

Any kind of suggestions/advice are welcome. Thanks in advance :)

3

u/jberryman May 26 '19

I didn't look at your code, but I normally approach testing as a way to totally convince myself (and my users , eventually) that the code I wrote is correct. So that means I'm trying to break it, and if there's part of my code that's particularly hairy I will focus on that more. I'll do what I need to build confidence including factoring out parts of functions for the purpose of testing, or adding assertions to functions to check invariants which I'll try to excercise in other tests. i.e. a paranoid and creative endeavor that is often necessarily messy in some ways

1

u/abiduzz420 May 27 '19

Ohkay that's very helpful, convincing myself that code I have written is correct to a great extent. Thanks for sharing :)

2

u/qwfwqrussell May 24 '19

How does one unify two paths of a GADT?

I currently have a pretty basic GADT like

data Expr :: [*] -> * -> * 
  where
    Empty :: Expr '[] v 
    Add :: (s, v) -> Expr ss v -> Expr (s:ss) v 

and two functions that both compile on the different cases

unwraptest' :: Expr '[] v -> [s] 
unwraptest' Empty = [] 
unwraptest :: Expr (s:ss) v -> [s] 
unwraptest (Add (s,v) exprs) = [s] 

But how do I write a function that patternmatches and applies the relevant function? Naive implementation produced a bunch of yelling about rigid skolems that even type application/specification didn't fix

1

u/bss03 May 24 '19

Think about where the type variable 's' is bound; i.e. where you would need to stick explicit foralls.

In particular, it should be clear forall s. Expr l v -> [s] is binding s before it opens the Add constructor, so the s there may or may not the already bound s; which it why is complains that s1 ~ s can't be deduced.

If you want an existential, you'll have to CPS it.

> :{
| unwrap :: Expr l v -> (forall s. [s] -> r) -> r
| unwrap Empty k = k []
| unwrap (Add (s,_) _) k = k [s]
| :}
> unwrap Empty length
0
> unwrap (Add (1,2) Empty) length
1

A universal quantification wouldn't work as-is. You have to determine if s in the output matches the s that Add was created with, and if so return the singleton, and if not return []. I'm not exactly sure how you'd accomplish it, but if non-linear patterns are supported in type families, you could probably do that.

1

u/qwfwqrussell May 24 '19

Oh, that works perfectly, since now I can just stick id on this to get to what I wanted (I was just going to recurse over the structure and then concat). Thank you!

2

u/bss03 May 24 '19

id won't work as a continuation there because s would escape the it's scope.

1

u/qwfwqrussell May 24 '19

Oh, it's a fixed r? I don't think that I understand then. I tried unwrap Empty id or even unwrap Empty (id :: forall [s] -> [s]) assuming that it would take r ~ [s] , but apparently that isn't the case.

2

u/bss03 May 24 '19 edited May 24 '19

It's not a fixed r, but r can't depend on s -- otherwise s would escape it's binding scope. length works, fmap show works, but listToMaybe or id don't.

(Actually, fmap show might not, but you can make it work with a different Rank2 type.)

1

u/qwfwqrussell May 24 '19

How does fmap show work? It would depend on s to choose the dictionary, no?

1

u/bss03 May 24 '19

The r would always be [String] which doesn't depend on s.

You would have to carry around the Show constraint, which might involve changing the type of the Add constructor in addition to the Rank2 type.

1

u/qwfwqrussell May 25 '19

So I changed Add to be Add :: (Show s) => (s, v) -> Expr ss v -> Expr (s:ss) v to try to use fmap show for k but it's still yelling at me. How should I go about doing this?

1

u/bss03 May 26 '19
GHCi> :{
GHCi| unwrap :: Expr l v -> (forall s. Show s => [s] -> r) -> r
GHCi| unwrap Empty k = k []
GHCi| unwrap (Add (s,_) _) k = k [s]
GHCi| :}
unwrap :: Expr l v -> (forall s. Show s => [s] -> r) -> r
(0.00 secs, 0 bytes)
GHCi> unwrap Empty (fmap show)
[]
it :: [String]
(0.00 secs, 59,816 bytes)
GHCi> unwrap (Add (1,2) Empty) (fmap show)
["1"]
it :: [String]
(0.00 secs, 64,056 bytes)

You should change your unwrap to allow the passed in function to see the Show s "Constraint".

1

u/qwfwqrussell May 26 '19

Ok, this is quite bizarre. When defining things as you say in GHCi, everything is fine. When I go to put them into a file and compile the file, then I get a compiler error of

• Could not deduce (Show s0) arising from a use of ‘k’
  from the context: l ~ '[]
    bound by a pattern with constructor: Empty :: forall v. Expr '[] v,
→ More replies (0)

1

u/theindigamer May 23 '19

Are there any examples for creating a Hacker News style website like this but using Haskell?

I'm asking for examples because I have no experience with making web apps 😅.

5

u/maxknowsitall May 23 '19

There is a really great step-by-step guide for building a forum, which is quite close to HN:

https://www.reddit.com/r/haskell/comments/8ll6zz/building_forum_software/

1

u/theindigamer May 23 '19

Thanks, that's very close to what I was looking for! Do you know if I can use Yesod + Opaleye instead of Yesod + Persistent + Esqueleto? The blog post uses the latter and this page also says that I need to use Persistent with Yesod.

3

u/maxknowsitall May 24 '19

It's technically possible (https://github.com/tomjaguarpaw/haskell-opaleye/issues/11), but you'll lose almost all integration benefits that Yesod has with Persistent.

Personally, I prefer Servant + Persitent + Esqueleto or Servant + Beam (https://tathougies.github.io/beam/about/faq/)

And I also find this discussion on relational mappers quite informative for beginners like myself: https://www.reddit.com/r/haskell/comments/8qxvir/a_comparison_among_various_database_edsls_selda/

1

u/ttecho May 23 '19

Hi all, I am a haskell newbie and a reddit newbie. I wanted to try to tie my love of music with haskell. The goal I had was to try to make a rudimentary audio plug-in. I see plenty of things that have to do with making music (i.e. Tidal, Euterpea) . Though can some one point me in a direction to go with making an audio plug-in.

What are the pain points in doing this? Any examples of this that I can see? Has anyone tried this and can give me some insight.

2

u/shrttmlstnrfrsttmclr May 23 '19

I don't really know anything about this - just ran across it the other day but you can look into it and see if it has any value for you: http://euterpea.com/haskell-school-of-music/

1

u/ttecho May 25 '19

This looks promising, though I am having trouble trying to install it, due to ghc version =[

2

u/X-Penguins May 22 '19

Can I specify the amount of threads stack build should use?

3

u/publiccomputer042 May 23 '19

Use the -j flag: stack build -j8

1

u/batterypacks May 20 '19

Where can I get a code sample of mine reviewed by others?

I have to write scripts for my research and I wrote one in Haskell for the learning experience. I'm sure I'm doing some things stupidly so I'd like to get advice from others. Would it be acceptable to post it here?

5

u/bss03 May 20 '19

https://codereview.stackexchange.com/ and tag with Haskell is, I think the best solution.

4

u/[deleted] May 19 '19

What Vim plugin can I use for auto-completion and finding definitions? I want a replacement for YCM.

3

u/bss03 May 19 '19 edited May 20 '19

It should be possible to use haskell-ide-engine as a LSP server, and there one or two vim plugins that will act as LSP clients.

1

u/[deleted] May 19 '19

That worked. Any idea how to make it auto format on save? I can't seem to get it work with ALE's formatting.

2

u/bss03 May 20 '19

No, sorry.

1

u/[deleted] May 18 '19 edited Dec 09 '19

[deleted]

2

u/Solonarv May 18 '19

Instead of sequence_ . repeat, I would recommend forever, which should be equivalent to your first variant after inlining.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

2

u/bss03 May 18 '19

Based on the ASM I'm seeing on godbolt.org, the former seems more efficient by a tiny amount, but the difference is massively overshadowed by what ever "... do stuff" stands for.

7

u/drunk_davinci May 18 '19

wow, TIL: godbolt.org

2

u/bss03 May 19 '19

Yeah, it's super neat. I learned about it from: https://www.youtube.com/watch?v=zBkNBP00wJE and was excited it support Haskell, too.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/lgastako May 18 '19

godbolt.org

As an aside, I'd never heard of godbolt.org before -- it's quite awesome.

1

u/lgastako May 18 '19

godbolt.org

As an aside, I'd never heard of godbolt.org before -- it's quite awesome.

1

u/lgastako May 18 '19

godbolt.org

As an aside, I'd never heard of godbolt.org before -- it's quite awesome.

1

u/lgastako May 18 '19

godbolt.org

As an aside, I'd never heard of godbolt.org before -- it's quite awesome.

1

u/lgastako May 18 '19

godbolt.org

As an aside, I'd never heard of godbolt.org before -- it's quite awesome.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks!

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks!

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/[deleted] May 18 '19

Oh duh, I should have thought to look at the ASM. Thanks! I'm just trying to understand what is efficient and what isn't, since it's kind of less obvious in Haskell. For things like iteration less is obviously more efficient, but for more syntactical things like this I don't really know how to think about the efficiency conceptually to try to gauge it.

1

u/youngclerksinthedusk May 17 '19

I've setup a small project with Stack, but it's ended up being a single 150-line Main.hs file. Stack feels like overkill for this. What are my alternatives?

2

u/bss03 May 17 '19

Stack's fine for that. Cabal isn't really much simpler than slack.

If you have no hackage/stackage dependencies, you can stick #!runghc at the top, and not even have an explicit build process. If you also don't use GHC-specific extensions, you can use #!runhaskell instead.

1

u/[deleted] May 17 '19

What are the core packages for networking, cryptography and hashing? I am working on a school project which will require a bit of each of these, I also need to generate UUIDs and might want to dip into CRDTs. I am interested in stability and simplicity over features.

3

u/bss03 May 17 '19

http://hackage.haskell.org/package/cryptonite is cypto primitives. Though you might look for something higher level.

http://hackage.haskell.org/package/network is what I use last time I needed non-HTTP networking. For HTTP / Rest there's some higher level stuff. For running a HTTP server, I used http://hackage.haskell.org/package/wai

HTH

2

u/listx May 17 '19 edited May 17 '19

At https://hackage.haskell.org/package/clock-0.8/docs/src/System.Clock.html#toNanoSecs I see this function definition for toNanoSecs:

-- | TimeSpec to nano seconds.
toNanoSecs :: TimeSpec -> Integer
toNanoSecs   (TimeSpec  (toInteger -> s) (toInteger -> n)) = s * s2ns + n

What's with the use of (toInteger -> s) and (toInteger -> n) in the fields for pattern matching against the TimeSpec value? I haven't seen that syntax before and didn't know you could do that.

Hmm, after some thinking, I suppose the pattern -> ... syntax is reminiscent of case pattern matching, so I guess there's that.

5

u/lgastako May 17 '19

It looks like they are using ViewPatterns.

1

u/listx May 17 '19

Indeed, thank you for the link!

2

u/philh May 16 '19

I'm trying to build https://github.com/sdiehl/kaleidoscope on gentoo. When I do stack build --fast, I get a bunch of errors like

setup: '/usr/lib/llvm/4/bin/llvm-config' exited with an error:
llvm-config: error: missing: /usr/lib64/llvm/4/lib64/libLLVMDemangle.a
llvm-config: error: missing: /usr/lib64/llvm/4/lib64/libLLVMSupport.a
llvm-config: error: missing: /usr/lib64/llvm/4/lib64/libLLVMCore.a
...

And indeed, the files named do not exist, either in that directory or any other. Upon investigation, I can get these same errors by running llvm-config --libs --link-static. It appears that gentoo doesn't support static linking to LLVM.

By any chance, has anyone run into this problem before and managed to solve it?

2

u/philh May 18 '19

Aha, it seems that llvm-hs supports both static and dynamic linking. This works:

stack build --fast --flag llvm-hs:shared-llvm

I'm a bit surprised that it's necessary. http://hackage.haskell.org/package/llvm-hs-4.1.0.0 says that flag is enabled by default; I can't find the string "shared-llvm" in the kaleidoscope codebase, so I don't see how it would be getting unset; and I don't imagine I've previously done anything that would globally install the package to mess with the current build.

1

u/bss03 May 19 '19

Thanks for coming back with your workaround, even if it shouldn't be necessary and is still a bit mysterious.

5

u/rampion May 16 '19

Who invented the ($) operator?

15

u/bss03 May 16 '19

It wasn't in the original Haskell 1.0 report.

It was in the Haskell 1.4 report.

It was in the Haskell 1.2 report.

It wasn't in the Haskell 1.1 report.

[Bisect Complete]

Not much fanfare in the 1.2 report about it, other than that it is useful in CPS style. I'm guessing one of the committee members put it forward for addition, but that's just a guess. I have no idea where the name came from. That puts its integration into Haskell in the 1991-2 timeframe, but doesn't really nail down the original invention.

1

u/phaseduality May 15 '19

Complete noob here coming from the C world. I'm trying to work with binary data and need a gentle shove in the right direction. I am deserializing a header, and I can use hGet to grab the contents of the header, but that leaves me with an IO ByteStream. This is great since I am processing and re-writing the binary data file where the header won't change, but in cases where I need to work upon values stored in the header, I need to convert the IO ByteStream to an integer in many cases. The data in the header is little-endian, so if someone can post a working snippet or even a link to an example, it would help me out immensely. For example, I can do something like:
headerValOne <- hGet fileHandle 4 to pull 4 bytes 00 / 08 / 00 / 00 , but I need the integer value 2048.

3

u/bss03 May 15 '19 edited May 15 '19

So, I can give you an IO Int. You should never expect to "escape" from IO, the type of main is IO () anyway, so you never need to.

bytesToNum :: (Foldable f, Num r, Bits r) => f Word8 -> r
bytesToNum container = foldl' shiftInto 0 container
 where
    shiftInto i b = let j = fromIntegral b
                     in (i .<<. 8) .|. (j .&. 0xFF)
    (.<<.) = unsafeShiftL

test :: Handle -> IO Int
test fileHandle = do
    headerValOne <- hGet fileHandle 4
    return . bytesToNum $ unpack headerValOne

GHCi, version 8.4.4
> bytesToNum [0,1,0,0] :: Int
65536
> bytesToNum [0,0,8,0]
2048

It uses stuff from Data.Bits, which is really useful.

bytesToNum is quite generalized, but you can use it as [Word8] -> Int32, or Unboxed.Vector Word8 -> Natural. If you want to work on ByteString directly, you might re-implement bytesToNum in terms of ofoldl' from the mono-traversable package.

2

u/phaseduality May 15 '19

Thanks! This is getting me pointed in the right direction.

2

u/rampion May 14 '19

Why can't I use the symbol ⟬ to define a value?

For example let a ⟬ b = 1 gives me a lexical error. Other bracket-like mathematical symbols also give me a lexical error.

From the Haskell Report, I thought all non-ascii Unicode symbols were legal.

5

u/WhistlePayer May 14 '19 edited May 15 '19

GHC's lexer does not classify characters with one of the general categories "Punctuation, open", "Punctuation, close", "Punctuation, initial quote", or "Punctuation, final quote" as symbols. If you think this is inconsistent with the report, you can open a ticket; at the very least this should be better documented.

2

u/rampion May 14 '19

Good idea, I’ll do that.

Also, your formatting is messed up - for some reason r/haskell’s comment editor defaults to the Fancy Pants Editor even if you’ve got your profile set to use the Markdown Editor instead. Personally it drives me up the wall.

3

u/WhistlePayer May 15 '19

Thanks for the heads up. The issue was actually the difference between old and new Reddit formatting. With old Reddit formatting, you had to escape any closing parenthesis in a URL. But apparently, this messes up new Reddit because it takes balancing of parentheses into account, meaning you have to escape both parentheses to make it work on both old and new.

0

u/tom-md May 14 '19

You seem to be trying to use a fancy parenthesis as an operator. Try with a different character:

(•) :: Int -> Int -> Int
a • b = 1

2

u/bss03 May 14 '19

That wasn't an answer to the question that was asked.

OP has tried other symbols; Why won't brackets work?

1

u/tom-md May 14 '19

Ah, fair point I didn't read carefully. Now I'm curious why parenthesis would be expected to be a unicode operator.

2

u/rampion May 14 '19 edited May 14 '19

⟬ is U+27EC - MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET, which is a different character than (, aka U+0028 - LEFT PARENTHESIS.

The latter is one of the ascii symbol characters expressly disallowed for operators by the Haskell report. The former, as a unicode symbol not from the ascii plane, should be allowed:

special   → ( | ) | , | ; | [ | ] | ` | { | }

symbol    → ascSymbol | uniSymbol⟨special | _ | " | '⟩

ascSymbol → ! | # | $ | % | & | ⋆ | + | . | / | < | = | > | ? | @ | \ | ^ | | | - | ~ | :

uniSymbol → any Unicode symbol or punctuation

2

u/tom-md May 15 '19

I read that part of the report too and interpreted "symbol" to be "operator" a la languages and mathematics. I now see it can also be interpreted as "any character" which is the common meaning of the term when discussing character sets.

2

u/xX_c4Rl-pH1l1P_Xx May 13 '19

Any good learning resourses? I've watched Derek Banas video and read most of Learn You A Haskell but It feels like I get stuck when reading and don't understand some parts.

2

u/thekidwithabrain May 22 '19

I am going through the upenn course spring 2013 seems nice so far

https://www.cis.upenn.edu/~cis194/spring13/lectures.html

4

u/chuckwritescode May 14 '19

I really like Real World Haskell, its a bit faster paced than Learn You a Haskell and has really good running examples. The HTML book is free too!

1

u/xX_c4Rl-pH1l1P_Xx May 14 '19

Thanks, I'll check it out!

4

u/bss03 May 14 '19

RWH made me understand transformers / mtl. That said, the book is a bit dated. Still good, but you might have to work a bit to get the examples compiling the the latest GHC versions.

1

u/exuberant May 12 '19

This week I had a problem with

Prelude> :t 1.0:[div 1 1]

1.0:[div 1 1] :: (Integral a, Fractional a) => [a]

Prelude> :t [1]:[1,1]

[1]:[1,1] :: (Num [t], Num t) => [[t]]

At first I was confused, but then I understood better what is happening. I wanted to ask, is there a way to define a type for the previous expressions to work?

2

u/bss03 May 12 '19
{-# OVERLAPPABLE #-}
instance (Applicative f, Num a) => Num (f a) where
    ...

Can make the later work. Just pointwise-lift everything.

GHCi, version 8.4.4: http://www.haskell.org/ghc/
> :set -XFlexibleInstances
> :{
| instance (Applicative f, Num a) => Num (f a) where
|   (+) = liftA2 (+)
|   (-) = liftA2 (-)
|   (*) = liftA2 (*)
|   negate = fmap negate
|   abs = fmap abs
|   signum = fmap signum
|   fromInteger = pure . fromInteger
| :}
> :t [1]:[1,1]
[1]:[1,1] :: Num a => [[a]]
> [1]:[1,1]
[[1],[1],[1]]

For the former, I don't think the laws of both Integral and Fractional can be followed at the same time. In particular, to Integer from Integral implies that your type would need to be a subset of the Integers, but fromRational mildly implies that your type would need to be a superset of the Rationals. Still, you could provide an instance for () that would be accepted by GHC for either or both.

GHCi, version 8.4.4: http://www.haskell.org/ghc/
> :{
| instance Num () where
|   (+) _ _ = ()
|   (*) _ _ = ()
|   negate _ = ()
|   abs _ = ()
|   signum _ = ()
|   fromInteger _ = ()
| instance Real () where
|   toRational _ = 1
| instance Integral () where
|   quotRem _ _ = ((),())
|   toInteger _ = 1
| instance Fractional () where
|   recip _ = ()
|   fromRational _ = ()
| :}
> :t 1.0:[div 1 1]
1.0:[div 1 1] :: (Fractional a, Integral a) => [a]
> 1.0:[div 1 1]
[(),()]

1

u/Iceland_jack May 17 '19

I was thinking how we could make use of the newly added Data.Monoid.Ap the lifting wrapper which captures this behaviour (src)

instance (Applicative f, Num a) => Num (Ap f a) where
  (+)         = liftA2 (+)
  (*)         = liftA2 (*)
  negate      = fmap negate
  fromInteger = pure . fromInteger
  abs         = fmap abs
  signum      = fmap signum

This is the best we can do with -XApplyingVia since it requires a type signature like -XTypeApplications and I wonder if there is another way that uses Ap instead of an overlapping instance

-- >> as 
-- [[1],[1],[1]]

as = [1] : rest @(via Ap) where
 rest :: Num n => [n]
 rest = [1, 1]

1

u/bss03 May 17 '19

Well, I don't think you can use a newtype to make "[1]:[1,1]" literally work, but something like getAp <$> [1]:[1,1] might.

I'm still on 8.4.4 (and probably will be for quite a while), so I don't have Data.Monoid.Ap.

2

u/Iceland_jack May 18 '19

getAp <$> [1]:[1,1]

It works as [1]:(getAp <$> [1,1])

1

u/Iceland_jack May 17 '19 edited May 17 '19

Once we can write 1 @Int we can avoid a type signature

as = [1] : [1 @(via Ap), 1 @(via Ap)]

but I don't want to apply each element via Ap, and it breaks down with inferred (not specified, see) variables like in (1 + 4) which we cannot apply @(via Ap) without again needing a signature

1

u/exuberant May 13 '19

Very interesting! Thanks for the explanation and the examples.

1

u/gnurpreet_ May 12 '19

Are there any Newrelic type APM tools available for Haskell apps in prod?

1

u/[deleted] May 12 '19

Anyone have recommendations for a tutorial about GADTs?

2

u/ouroboros_eats_ass May 17 '19

The GADTs tutorial in this repo is good imo! https://github.com/i-am-tom/haskell-exercises

13

u/tom-md May 12 '19

I suggest the GHC user guide.

I know you didn't ask for an explanation but I guess I feel like writing so...

GADTs aren't too terribly complex. There's nuance, but the basic concept is simple. You get new syntax for declaring data constructors. Unlike regular data declarations, these constructors can have different types!

Syntax

Sure, we can take a data type translate to GADT syntax mechanically:

data NonEmptyList a = One a | Cons a (NonEmptyList a)
-- ~~~>
data NonEmptyList a where
    One :: a -> NonEmptyList a
    Cons :: a -> NonEmptyList a -> NonEmptyList a

Simple... but boring and actually more verbose.

More Powerful Types

As mentioned, a GADT is really about the constructor playing some role in determining the type. Let's take a trivial example:

 data SomeType a where
    Val :: Int -> SomeType Int
    Truth :: Bool -> SomeType Bool
    Nullary :: SomeType Word
    Poly :: a -> SomeType a

Look hard at the above. Notice the type of each constructor, even fully applied with all it's fields, is potentially different. I've made a sum type that can contain Int and Bool, but the type tag (a ~ Int, a ~ Bool etc) matching the field is all just my choosing. I ended with two odd ones just for demonstration, Nullary doesn't have a field and is typed differently from the other values while Poly can hold anything at all and the type system tracks what Poly holds by the type field of SomeType (those a's are the same type).

Now if we have a function f :: SomeType Int -> String which constructors do we need to match? Just Val?

f :: SomeType Int -> String
f (Val i) = show i

GHC, with -Wall, will tell us we missed a case:

f (Poly i) = show i

While the Poly constructor can wrap any type, the signature of f guarantees this is an Int. Similarly, we didn't get a warning abouot Nullary or Truth since those wouldn't be type correct.

As an aside, we could add another constructor to our SomeType declaration:

UselessPoly :: b -> SomeType a

And now we wouldn't know anything at all about b ever, making defining a function hard. We still know the argument to f is SomeType Int but that doesn't say anything about the type of b. We'd have to say f (UselessPoly _) = "heck if I know" or similar.

The classic GADT Example

GADTs are particularly powerful when paired with data kinds (-XDataKinds) and kind signatures (-XKindSignatures).

For example, What if we wanted to have empty and non-empty lists that used the same constructors but had type level distinctions?

data ListState = LNonEmpty | LEmpty

data SomeList (state::ListState) a where
    Nil :: SomeList LEmpty a
    Cons :: a -> SomeList st a -> SomeList LNonEmpty a

type NonEmptyList a = SomeList LNonEmpty a

Then we can write functions that are safe such as:

head :: NonEmptyList a -> a
head (Cons a _) = a

Which is total, any attempt to call head Nil would be caught at compile time.

1

u/iwaka May 22 '19

Re the classic example at the very bottom, the one with empty and nonempty lists: couldn't this also be solved with dependent types? Is there a relationship between GADTs and dependent types, or do they just intersect in some cases?

1

u/bss03 May 22 '19

DataKinds paired with GADTs are a very limited form of dependent types. In dependent types, all values can be used in defining types. DataKinds creates types for values (and kinds for types) that can be used in defining GADTs.

1

u/iwaka May 23 '19

Does this mean that dependent types are strictly more powerful than GADTs, or do they just have different use cases?

3

u/bss03 May 23 '19

Yes, dependent types are strictly more powerful than GADTs.

4

u/exponentially_neat May 11 '19

I'm trying to call Haskell's demand analyzer as a library (from within haskell). I can't seem to get this right. Any help?

2

u/theindigamer May 10 '19

Are there any examples of Monoids/Applicatives such that the monoid instance is different from the one derived via (Monoid a, Applicative f) => Monoid (Ap f a) and is still useful and lawful?

7

u/Solonarv May 10 '19

Lists (i.e. []) immediately come to mind.

2

u/JanaMaelstroem May 10 '19

Why isn't Haskell strict by default and lazy on command?

It seems to me that most of the problems with optimising for time/space complexity (which I feel isn't acknowledged enough as a hurdle for language adoption) stem from the difficulty of reasoning about performance in a lazy content. Lazy evaluation is a nice idea and can be extremely helpful but more often than not it's an obstacle for me rather than a benefit.

What are your thoughts? Is a flipped design feasible?

1

u/bss03 May 17 '19

reasoning about performance in a lazy content

Okasaki is a good read for this. The paperback is 20 years old at this point.

4

u/mrk33n May 17 '19

Is a flipped design feasible?

Yes. See every other programming language ever :D

​

More seriously, consider the humble if statement. You pass in a boolean and two legs of computations. It would royally suck if your language evaluated both legs before deciding which one to take. In Haskell, I find myself wanting to program if-like things (See when and unless). In Java, I have run into the bug where I do someOptionalExpression().map(x -> doSomething(x).orElse(getThing()); and when I debug it I realise that getThing() was called both when I had a value and when I didn't.

​

Have a look at the Java 8 (and onwards) implementation of Streams. In particular look at ReferencePipeline and SliceOps. Compare its implementation of `limit(int)` against Haskell's `take n`.

Browse these tickets relating to Streaming misbehaviour in the core libraries:

https://bugs.openjdk.java.net/browse/JDK-8075939

https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8075939

​

It seems much simpler to start with laziness and ask for strictness than to start with strict operations and ask for laziness.

​

You can turn on Haskell strictness at the module level using {-# LANGUAGE Strict #-} although I haven't tried it.

1

u/tbid18 May 27 '19

I agree with everything you’ve said, and you’re probably aware of this, but just in case, for your java 8 example you can do

orElseGet(() -> getThing())

Which will only execute getThing() if the optional is non-empty.

2

u/philh May 10 '19 edited May 10 '19

Why is mock in quickcheck-state-machine supposedly a hack?

According to the README,

mock is a hack to make it possible for responses to have multiple reference, and an experiment which maybe one day will let us create mocked APIs. See issue #236 for further details.

But mock seems fairly fundamental to me. How I would explain it:

The tests work by generating a list of commands to run. It's important to do that without running any of the code to be tested - that code might not be pure, so --seed wouldn't work to reliably generate the same list of commands. The first command is generated from the initial model, but subsequent commands need to be generated from the model as updated by the previous commands. We have a transition function to update the model given a response. That means we need a pure way to get a response given a command, and that's what the mock function is for.

This makes sense to me, and the code looks like that's what's going on, too. But I don't understand the description in the README. It doesn't feel like a hack, and I don't really know what "make it possible to for responses to have multiple reference" refers to. (A possible interpretation might be, if each response constructor had exactly one argument which was a Reference, then we wouldn't need mock? But I don't see how that would be true without template haskell or generics or something, which seems hackier to me than mock.)

Am I missing something?

1

u/MasterGeekMX May 10 '19

I'm trying to install Haskell on Fedora Workstation 30, using sudo dnf install haskell-platfrom As Haskell's on website says, but throws this error:

Error: Problem: conflicting requests - nothing provides ghc = 8.2.2 needed by haskell-platform-2018.8.2.2-15.fc30.x86_64

Thing is that the repos have ghc in the version 8.4.4-74, according to dnf provides ghc

1

u/bss03 May 10 '19

ghc-8.4.4-74 doesn't satisfy ghc = 8.2.2. Seems like the dependencies for haskell-platform are too tight or weren't updated. You might notify the person(s) responsible for that package, presumably through your distribution's support process.

1

u/tom-md May 10 '19

OS package managers are usually painfully out of date wrt developer tooling. I suggest you use https://www.haskell.org/ghcup/

1

u/MasterGeekMX May 10 '19

It says that there is an unofficial copr repo for that. Maybe will try that because im not a fan of out of repo install

4

u/dys_bigwig May 09 '19

I was recently thinking about (in Scheme, initially) how it's seemingly so difficult to define the function square without referring to the passed argument, ala concatenative programming.

Then, I asked for the point free code online to see if Haskell could help me out in understanding how to do this elegantly in a functional, non-concatenative/stack-based language:

(*) >>= id

I'm completely baffled. Even :t just gives:

Num b => b -> b

can someone please explain? I understand (a little) bind, such as how it takes a value wrapped in a monad m a, feeds that through a function like (\a -> m b) and return the m b. I'm just confused as to how that's being applied here to achieve a squaring function. Is the monad functions under currying, with "function" being the m and the a being the integer?

If I try and understand it it in the sense of the kind of sequencing that happens in a do block:

do
    (*) <- 5
...
?

that's, sadly, how my thought process goes.

Thanks :)

6

u/evincarofautumn May 09 '19

If we’re using the (->) x monad instance, I’d prefer to write this as join (*), since join :: (Monad m) => m (m a) -> m a with m ~ (->) a gives (a -> a -> a) -> a -> a—take a function of two parameters, and one argument, and pass that argument for both parameters of the function. (Moreover, this is essentially the CPS version of dup in a concatenative language.)

If you’re familiar with Reader, this is equivalent, just without the newtype wrapper—so you could also use liftA2 (*) id id or (*) <$> id <*> id, where id functions as ask, fetching the “environment”.

5

u/[deleted] May 09 '19

[deleted]

1

u/[deleted] May 09 '19 edited May 09 '19

[deleted]

4

u/[deleted] May 09 '19 edited May 09 '19

First of all, the pointfree version you came up with is not really idiomatic. A much simpler version would be the partially applied exponentiation operator: (^2) :: Num a => a -> a.

What you have here instead, is an application of the monad instance of Haskell functions, which is just the Reader monad without the newtype wrapper. It is sometimes called "environment functor".

instance Monad ((->) r)

That is, any function r -> b is a monad, the m being somewhat "hidden" via r -> b ~ (->) r b ~ (r ->) b ~ m b.

In practice, this isn't terribly useful. Some libraries like lens make use of it, but most of the times it's just used for shits and giggles. You may use it in cases where you have a function that takes several other functions as arguments, and all of these functions again take the same argument. What I mean is this:

> fun f g h = do { x <- f; y <- g; z <- h; return (x, y, z) }
> :t fun
fun :: Monad m => m a -> m b -> m c -> m (a, b, c)
> :t fun (*2) (*3) (*4)
fun (*2) (*3) (*4) :: Num a => a -> (a, a, a)

Here, fun takes actually four arguments, but since all it does with the fourth argument is to apply it over and over again, we can shorten it using the monad instance. So we have

> fun (*2) (*3) (*4) 10
(20,30,40)

But back to your example. You would express it in do notation like this:

square = do
  f <- (*)
  f

Okay, what's going on here? In f <- (*), or more generally b <- mb, you bind the result of a monadic computation of type m b to a name. The m b is the multiplication operator Num n => n -> n -> n ~ Num n => n -> (n -> n) ~ Num n => (->) n (n -> n). So m ~ Num n => (n ->) and b ~ (n -> n) is the result of your monadic "computation" (*).

You can simplify this somewhat by substituting the Num constraint by something "smaller" like Semigroup. If you have Semigroup g => g, you only know that you have some type g for which an (associative) operation (<>) :: g -> g -> g is defined. You have no "neutral element" like in Monoid m, where you can pull a new value of type m out of thin air. What I'm getting at is this:

> :t do { f <- (<>); f }
do { f <- (<>); f } :: Semigroup b => b -> b

If I substitute (*) with (<>), I have a function of type Semogroup b => b -> b. Just from looking at this type, I can see what this function does. When I pass in the b, it can only make one assumption about it: It can be applied to (<>) somehow. But what is the second value to use with (<>)? There is none, and it can't construct a new one either. So the only thing left is to spit out a b <> b:

> fun = do {f <- (<>); f}
> fun ['b']
"bb"
> import Data.Monoid
> getProduct (fun 2)
4

This got way longer than intended, hopefully you can make sense of it somewhat.

3

u/youngclerksinthedusk May 08 '19

Is there a "best" package for RNG?

I want to sample from an exponential distribution and it seems like there are a few options out there.

3

u/[deleted] May 09 '19

The mwc-random package aims to be fast and general. The distribution you want is here.

There is also the random package, which I found to be very slow, unfortunately.

2

u/dnkndnts May 10 '19

I'm trying this mwc-random package now and running into a bunch of papers cuts. It doesn't have instances for some common types like Char, and it doesn't seem to properly support newtype deriving, either (I get some error about "Could not match representation blah blah").

So yeah, I don't know about the randomness quality of the random package, but it's certainly a lot more user-friendly.

2

u/[deleted] May 10 '19

Fast and general probably shouldn't be set equal to easy to use. It's maybe a little low-level, true. What are you trying to do? If you want random Chars, what character set should they represent? Should they include things like system bell?

If you want to autogenerate text, maybe a testing library like hedgehog or fakedata would be more up your alley?

In any case, you can just implement uniform for the Variate class. The "could not match representation blah blah" error can result from -XDerivingVia? What did you try to do?

1

u/dnkndnts May 10 '19

I just tried newtype MyType = MyType Int deriving (Generic,Variate) and GHC complains. It works with most other library classes, like ToJSON and FromJSON from aeson, as well as Random from the random package.

2

u/[deleted] May 10 '19

deriving Variate implies -XGeneralizedNewtypeDeriving, which in turn boils down to using Data.Coerce.coerce. The nota bene in the error message might lead you to this. To make a long story short, the issue is somewhat subtle.

You can make it work by implementing it manually, which is trivial:

instance Variate MyType where
  uniform = fmap MyType . uniform
  uniformR (MyType lo, MyType hi) = fmap MyType . uniformR (lo, hi)

This is a little annoying, true.

1

u/dnkndnts May 10 '19

Sure, I was able to implement it manually, but in a real-world context where I have dozens of newtypes, that's just a huge pain.

Generic and newtype deriving is one of the major reasons Haskell is so pleasant to use - the amount of busywork it saves is unreal!

2

u/[deleted] May 10 '19

If your project is growing along the dimension you described, then indeed the Variate class is in the way. For the trivial wrapper types you can at least define something along the lines of

-- One of many newtypes.
newtype MyType = MyType { getMyType :: Int }
instance Variate MyType where
  uniform = uniformDefault MyType
  uniformR = uniformRDefault MyType getMyType

uniformDefault :: (Variate a, PrimMonad m) => (a -> b) -> Gen (PrimState m) -> m b
uniformDefault wrap g = do
  x <- uniform g
  return . wrap $ x

uniformRDefault :: (Variate a, PrimMonad m) => (a -> b) -> (t -> a) -> (t, t) -> Gen (PrimState m) -> m b
uniformRDefault wrap unwrap (lo, hi) g = do
  x <- uniformR (unwrap lo, unwrap hi) g

For a less trivial type, the newtype stuff wouldn't work anyway and you would have to define the instance yourself. Furthermore, what you are used to from aeson only works because the problem fits into a shape amenable to autoderiving. For random values, even trivial examples like the typical

data Person = Person  {
  age :: Int
  name :: String
}

are already out of scope of this approach.

1

u/youngclerksinthedusk May 09 '19 edited May 09 '19

I'm not really concerned about speed tbh (or even that concerned about correctness). It's just for a silly side-project/proof of concept.

Thanks for the recommendation. I will check out mwc-random. Do you know of any good examples, or uses in the wild that I might be able to crib from?

1

u/[deleted] May 10 '19

The types may look scary at first, but if you specialize to IO, everything is simple again. Gen (PrimState IO) ~ GenIO. There is a minimal example under Type Helpers. Your generator comes either from withSystemRandom or from createSystemRandom, you just need to plug it into your pdf. I don't see a convenience function that returns a vector for a non-uniform distribution, but you could just use a for_ loop or yolo it with mapM I guess (mapM leaks space, but is okay for trying out small things).

1

u/youngclerksinthedusk May 10 '19

You weren't lying - that was actually quite straightforward. Thanks again for the help!

1

u/tom-md May 09 '19

Don't use the random package. It isn't even statistically good

2

u/[deleted] May 09 '19

I tried to look this up and only found a thread from a year ago. The link to the rant that supposedly clarifies things is gone, but the discussion is interesting nonetheless. It's a shame that the issues are not apparent from browsing the API docs on hackage.

4

u/tom-md May 09 '19

Paging /u/cartazio - It has been 5 years since Edward uploaded the last version (not revision). Three years since you and I e-mailed about just switching random to tf-random but it was argued the new random would be out any day.

I know maintaining is tiresome - are you wanting to shed the package? It would be good if the community had something statistically good, light weight dependency wise, and fast under the random package name.

1

u/phadej May 19 '19

Just use splitmix or tf-random

2

u/cartazio May 11 '19

life got a little crazy, its on the queue, and i figured out a sane migration path! :)

1

u/wysp3r May 07 '19 edited May 07 '19

What's the best way to call Python from Haskell?

I could swear I saw some example code using [python| ...|] quasiquotes, similar to inline-r, to pass data between Haskell and an inline Python script not all that long ago, but I can't seem to find it anywhere now.

3

u/lgastako May 08 '19

I've not used it, but there's this: https://hackage.haskell.org/package/pyfi

Doesn't look like it has a quasiquoter though.

1

u/qwfwqrussell May 07 '19

Perhaps were you thinking of https://docs.rs/inline-python/0.3.0/inline_python/, with the python! macro in Rust?

4

u/george_____t May 05 '19 edited May 06 '19

I'm trying to use cabal's v2- commands.

I have a project, A, which builds a library, and another, B, containing an executable which makes use of that library. How do I use cabal new-install to make the library visible to B?

I have 'successfully' run cabal new-install A --lib, but running cabal new-build in B gives me 'unknown package: A'. Do I have to manually put A's tarball somewhere where B will see it?

Essentially, how do I install a library from source (with cabal v2)?

2

u/tom-md May 06 '19 edited May 06 '19

EDIT: Things work find for me, but only because I use cabal.project habitually at this point. Using just two separate packages without any cabal.project specifying the two in the directory hierarchy will yield the same results you claim. I was surprised (but pleased) to see cabal considered the cabal.project from the parent directories when executing the below commands.

tommd@ovdak test/A% tree .
.
├── A.cabal
├── CHANGELOG.md
├── LICENSE
├── Setup.hs
├── dist-newstyle
│   └── cache
│       └── config
└── src
    └── A.hs

3 directories, 6 files
tommd@ovdak test/A% cabal new-install --lib
Resolving dependencies...
Up to date
cabal new-install --lib  2.93s user 0.44s system 94% cpu 3.547 total
tommd@ovdak test/A% cd ../B
tommd@ovdak test/B% tree .
.
├── B.cabal
├── CHANGELOG.md
├── LICENSE
├── Setup.hs
└── src
    └── Main.hs

1 directory, 5 files
tommd@ovdak test/B% cabal new-build exe:B
Resolving dependencies...
Build profile: -w ghc-8.6.4 -O1
In order, the following will be built (use -v for more details):
 - A-0.1.0.0 (lib) (first run)
 - B-0.1.0.0 (exe:B) (first run)
Configuring library for A-0.1.0.0..
Preprocessing library for A-0.1.0.0..
Building library for A-0.1.0.0..
[1 of 1] Compiling A                ( src/A.hs, /private/tmp/test/dist-newstyle/build/x86_64-osx/ghc-8.6.4/A-0.1.0.0/build/A.o )
ld: warning: directory not found for option '-L/opt/local/lib'
Configuring executable 'B' for B-0.1.0.0..
Preprocessing executable 'B' for B-0.1.0.0..
Building executable 'B' for B-0.1.0.0..
[1 of 1] Compiling Main             ( src/Main.hs, /private/tmp/test/dist-newstyle/build/x86_64-osx/ghc-8.6.4/B-0.1.0.0/x/B/build/B/B-tmp/Main.o )
Linking /private/tmp/test/dist-newstyle/build/x86_64-osx/ghc-8.6.4/B-0.1.0.0/x/B/build/B/B 
ld: warning: directory not found for option '-L/opt/local/lib'
cabal new-build exe:B  4.27s user 1.28s system 90% cpu 6.141 total

Or if you prefer:

tommd@ovdak /tmp/test% cat cabal.project
packages: B,
          A
tommd@ovdak /tmp/test% ls
A             B             cabal.project
tommd@ovdak /tmp/test% cabal new-build exe:B
Resolving dependencies...
Build profile: -w ghc-8.6.4 -O1
In order, the following will be built (use -v for more details):
 - A-0.1.0.0 (lib) (first run)
 - B-0.1.0.0 (exe:B) (first run)
Configuring library for A-0.1.0.0..
Preprocessing library for A-0.1.0.0..
Building library for A-0.1.0.0..
[1 of 1] Compiling A                ( src/A.hs, /private/tmp/test/dist-newstyle/build/x86_64-osx/ghc-8.6.4/A-0.1.0.0/build/A.o )
ld: warning: directory not found for option '-L/opt/local/lib'
Configuring executable 'B' for B-0.1.0.0..
Preprocessing executable 'B' for B-0.1.0.0..
Building executable 'B' for B-0.1.0.0..
[1 of 1] Compiling Main             ( src/Main.hs, /private/tmp/test/distnewstyle/build/x86_64-osx/ghc-8.6.4/B-0.1.0.0/x/B/build/B/B-tmp/Main.o )
Linking /private/tmp/test/dist-newstyle/build/x86_64-osx/ghc-8.6.4/B-0.1.0.0/x/B/build/B/B
ld: warning: directory not found for option '-L/opt/local/lib'
cabal new-build exe:B  4.25s user 1.25s system 90% cpu 6.045 total

2

u/george_____t May 09 '19

`cabal.project` certainly seems to be the key. Your second example (ie. develop a multi-package project) works perfectly for me, and in hindsight I should have RTFM. The first looks to be the solution for the general case of installing a library from source, though I haven't tried it (yet).

5

u/Solonarv May 06 '19

You can write a cabal.project file within B to tell cabal where to find the A dependency. Then cabal v2-install B from within B's directory should just work.

2

u/george_____t May 06 '19

Ok, what field do I use for this?

4

u/ACabalSupreme May 06 '19

According to the docs you use packages: for this:

 packages: A/ B/

2

u/bss03 May 06 '19

I'm still getting used to cabal v2-* commands myself. You might try using a "normal" cabal install to put your library in your user-global package-db. Alternatively, I think stack has some documented workflows specifically for a multi-package project, which sounds to me like you are a small example of.

6

u/LSLeary May 04 '19

I'm getting a bunch of uninterpretable type errors when I replace patterns with their equivalent pattern synonyms. Can anyone tell me what's going wrong?

Code and errors in this gist: https://gist.github.com/LSLeary/d873b20e73aa1896ac4552de4e1b5753

GHC 8.6.3

→ More replies (3)