Cale 2017-03-01 04:45:32
(by throwing an exception or running forever, as that's the only kind of thing which could be of an arbitrary type)
lpaste_ 2017-03-01 04:45:57
dramforever pasted "kubunto please see this" at http://lpaste.net/353103
Cale 2017-03-01 04:45:57
any result type* you wanted it to
dramforever 2017-03-01 04:47:13
jnj: That's how 'unknown type' works
lyxia 2017-03-01 04:47:13
delYsid: count p = fmap (+1) (p *> count p) <|> return 0
dramforever 2017-03-01 04:47:14
Crap
Cale 2017-03-01 04:47:21
jnj: If you wanted it to mean "There exists some type b for which someThing produces a result of type b, but you can't know which", that's even less useful, because you could never ever use such a result (since you don't know what type it is, you'll never be able to inspect it)
dramforever 2017-03-01 04:47:23
That's *not* how 'unknown type' works
jnj 2017-03-01 04:47:43
Cale: I guess the error is confusing me a little: http://lpaste.net/353102 but i'll try and wrap my head around it
Cale 2017-03-01 04:47:48
You could do that with an existential type, but not a useful existential type.
jnj 2017-03-01 04:47:49
I don't see why that paste does not typecheck
Cale 2017-03-01 04:48:07
jnj: Because that function clearly produces a String
Cale 2017-03-01 04:48:15
Not a value of type b
Cale 2017-03-01 04:48:28
What if I want it to produce an Integer for me?
Cale 2017-03-01 04:48:51
I'm allowed to specify that b is Integer when I use the something function.
jnj 2017-03-01 04:49:13
I was expecting Haskell to infer that b == string I suppose, but I can see the problem in that
jnj 2017-03-01 04:49:52
Can I have "something" return a type class?
kubunto 2017-03-01 04:50:11
what does this mean: Graph [Char] [Char] compared to (Num d, Num o) => Graph d o
Cale 2017-03-01 04:50:48
Well, functions at the value level have to produce values. Type classes are type-level things, and are only around at compile time.
Cale 2017-03-01 04:51:08
What are you trying to do?
dramforever 2017-03-01 04:51:11
jnj: The *caller* gets to choose what 'b' is
Cale 2017-03-01 04:51:39
Yeah, this would be clearer if all type variables were explicitly quantified
dramforever 2017-03-01 04:51:40
It means that I can call 'something', and *choose* b
dramforever 2017-03-01 04:52:01
kinda like an argument
Cale 2017-03-01 04:52:21
You'd have class X a where something :: forall b. a -> b
Cale 2017-03-01 04:52:46
Maybe what you're looking for is a class associated type
jnj 2017-03-01 04:52:51
That's producing the same error, I tried it but am not strong in forall.
Cale 2017-03-01 04:52:53
class X a where
Cale 2017-03-01 04:52:57
type XResult a
Cale 2017-03-01 04:53:05
something :: a -> XResult a
Cale 2017-03-01 04:53:13
instance X Int where
Cale 2017-03-01 04:53:19
type XResult Int = String
Cale 2017-03-01 04:53:29
something = const "hello world!"
dramforever 2017-03-01 04:53:42
jnj: It's *very* unclear about what you're trying to achieve
dramforever 2017-03-01 04:53:56
Can you like explain further?
Cale 2017-03-01 04:53:58
jnj: That's because it's equivalent to what you wrote
glguy 2017-03-01 04:54:17
jnj: you don't get to pick what b is when you're defining your function. the users of your function get to pick it, so you have to be ready for any choice the user makes, you can't guess string
Cale 2017-03-01 04:54:19
jnj: It's just (hopefully) clearer that the type of something says that it should work for all types b
Cale 2017-03-01 04:55:07
jnj: Haskell automatically sticks foralls in at the top level of type signatures to bind the type variables which occur free in them.
Cale 2017-03-01 04:55:30
e.g. when we write map :: (a -> b) -> [a] -> [b]
dramforever 2017-03-01 04:55:40
We're getting to far away from jnj I think
Cale 2017-03-01 04:55:41
it really means map :: forall a b. (a -> b) -> [a] -> [b]
Cale 2017-03-01 04:56:02
i.e. whatever map does, it must work for all choices of types a and b
Cale 2017-03-01 04:57:17
The way it accomplishes that is by not inspecting any values of type a or b, so that it's just passing the (pointers to) values around.
jnj 2017-03-01 04:58:17
this is what i wrote down, don't know if that makes sense
jnj 2017-03-01 04:58:18
http://lpaste.net/353105
jnj 2017-03-01 04:58:30
(which does not compile)
Cale 2017-03-01 04:59:05
Well, the type of getCell is highly suspicious
Cale 2017-03-01 05:00:02
You probably want either a multiparameter type class with a functional dependency, or you want an associated type
Cale 2017-03-01 05:00:17
(or you don't want a type class at all)
Cale 2017-03-01 05:00:54
Also, the Monad constraint is weird
delYsid 2017-03-01 05:01:17
lyxia: ahh, nice, thanks!
Cale 2017-03-01 05:01:24
There's very little you could do to create an action in an arbitrary monad apart from applying return, so it doesn't make much sense to bother with that
Cale 2017-03-01 05:01:43
class Row e a | a -> e where getCell :: a -> Int -> Maybe e
Cale 2017-03-01 05:01:47
makes more sense
Cale 2017-03-01 05:02:10
instance Row a (SimpleRow a) where ...
jnj 2017-03-01 05:03:02
I was thinking that some instances of Row might require getCell to run in for example the IO monad
Cale 2017-03-01 05:03:05
Yeah, but you haven't said that
jnj 2017-03-01 05:03:06
anyways, I'll rethink the entire thing anyways, as it's not the right way
Cale 2017-03-01 05:03:10
You said it works in *any* monad
jnj 2017-03-01 05:03:21
Oh
Cale 2017-03-01 05:03:37
So you're not required to use it in IO at all, you could use it in the list monad, or Maybe.
dramforever 2017-03-01 05:03:47
jnj: You got the type variable thing completely wrong
kubunto 2017-03-01 05:04:05
dramforever: i got how to escape the issue with an empty list
Cale 2017-03-01 05:04:18
We could also parameterise the class by a choice of monad
kubunto 2017-03-01 05:04:19
let k = Node "fitness" [] :: Num a => Graph a [Char]
dramforever 2017-03-01 05:04:23
When I have an expression e, and it is of type 'forall a. something something'
Cale 2017-03-01 05:04:23
and have that depend on the row type as well
Cale 2017-03-01 05:04:38
class Row m e a | a -> m e where
dramforever 2017-03-01 05:04:47
Then when I use 'e', *I* get to choose what 'a' is
Cale 2017-03-01 05:04:50
getCell :: a -> Int -> m (Maybe e)
Cale 2017-03-01 05:05:13
The "| a -> m e" means that the choice of a uniquely determines m and e
dramforever 2017-03-01 05:05:20
You know C++ templates or Java generics? It's a tiny bit like those
Cale 2017-03-01 05:05:35
The compiler will prevent you from writing more than one instance for any given type a
Cale 2017-03-01 05:05:47
but in exchange, it will infer m and e whenever it knows a
Cale 2017-03-01 05:05:54
(by looking for which instance applies)
Cale 2017-03-01 05:06:13
You can do some pretty fancy type level computation with this.
jnj 2017-03-01 05:06:19
I'll look into your suggestions, for now I need to read.. Thanks for your help
Cale 2017-03-01 05:06:56
Equivalently, using the newer TypeFamilies extension you could write:
Cale 2017-03-01 05:07:09
class Row a where
Cale 2017-03-01 05:07:25
type RowM a :: * -> *
Cale 2017-03-01 05:07:35
type RowElement a
Cale 2017-03-01 05:07:52
getCell :: a -> Int -> RowM (Maybe (RowElement a))
Cale 2017-03-01 05:08:50
and then when you write the instance, you get to specify what those type synonyms expand to, when applied to the particular type a
jnj 2017-03-01 05:09:02
that might work, thanks
merijn 2017-03-01 05:09:57
Any persistent users who can tell me whether I can have "compound" fields in my entities? i.e. I have a datatype "data Foo = Foo Int Int Int" and another thing that has "data Bar = Bar Foo Foo Foo", can I somehow represent that in persistent easily? i.e. I just want a flat row with 9 Int in my resulting database, but on the haskell side have 9 direct Int fields is annoying compared to nesting like that
Cale 2017-03-01 05:10:37
merijn: I know it's possible with groundhog, so I would be surprised if persistent didn't also do it
merijn 2017-03-01 05:11:10
Cale: I would expect something like that to be possible, but I haven't found a way yet
Cale 2017-03-01 05:12:13
Wow, persistent's documentation actually manages to suck more than groundhog's
merijn 2017-03-01 05:12:23
Cale: Word :p
merijn 2017-03-01 05:13:18
Honestly, the Yesod way with lots of MPTC mtl constraints leads me to understand the complaint about unscrutable Haskell documentation >.>
merijn 2017-03-01 05:14:25
Cale: I hadn't heard of groundhog before. Would you recommend it?
Cale 2017-03-01 05:14:57
Well, it's terrible, but we're using it, so that's something.
merijn 2017-03-01 05:15:05
Cale: ah...
Cale 2017-03-01 05:15:19
It's less terrible than many of the alternatives
merijn 2017-03-01 05:15:26
That doesn't sound like a ringing endorsement for being better than persistent
Cale 2017-03-01 05:15:59
But looking at these entity definitions from persistent, it seems groundhog does a way better job of letting you specify how things are mapped to the DB
Cale 2017-03-01 05:16:35
even if you have to write a weird yaml syntax and it silently ignores anything it doesn't understand
merijn 2017-03-01 05:17:06
Cale: yeah, but on the other hand I already figured out persistent now and I'm not tied to a schema anyway
merijn 2017-03-01 05:17:45
So investing similar time into something else which is, at best, only marginally better seems a waste
Cale 2017-03-01 05:18:00
https://hackage.haskell.org/package/groundhog-th-0.8/docs/Database-Groundhog-TH.html
Cale 2017-03-01 05:18:06
-- documentation by example
Cale 2017-03-01 05:19:41
The main reason we use groundhog at this point is to get some automatic migrations (it's not bad at doing all the really easy ones), and to get a little extra type safety for the very simplest queries we need to do
Cale 2017-03-01 05:20:02
We end up using postgresql-simple to do a lot of queries, because groundhog (like persistent) doesn't support joins
Cale 2017-03-01 05:20:43
(they're compatible)
Cale 2017-03-01 05:21:39
If you've used persistent, using groundhog is usually the same -- it was actually forked from persistent somewhere along the way
Cale 2017-03-01 05:21:54
But the template haskell shenanigans seems to be quite different
merijn 2017-03-01 05:23:19
Cale: Basically, what I mostly need is SQLite and preferably a conduit/pipes interface to query results
Cale 2017-03-01 05:23:20
https://github.com/lykahb/groundhog/blob/master/examples/basic.hs
kuribas 2017-03-01 05:23:55
Does using mutable state improve performance? (using STRefs for example)
merijn 2017-03-01 05:24:04
kuribas: "it depends"
merijn 2017-03-01 05:24:43
Cale: honestly, I don't think I really need joins atm
merijn 2017-03-01 05:25:31
Cale: Also, doesn't esqueleto provide joins for persistent?
kuribas 2017-03-01 05:25:47
I am amazed how much writing haskell code in a low level way can improve performance.
kuribas 2017-03-01 05:26:03
haskell is not very cache friendly.
brynser_ 2017-03-01 05:26:08
I think persistent would end up storing your Bar value as a single varchar, the contents being 'show '. At least that's what happened when I tried storing a product data type
merijn 2017-03-01 05:26:11
kuribas: That's the same in any language, knowing what you're doing is crucial for performance
merijn 2017-03-01 05:26:23
brynser_: That's for sum datatypes, yes
kuribas 2017-03-01 05:26:34
merijn: sure
Cale 2017-03-01 05:26:42
merijn: Yeah -- I have no idea how complete it is, but it claims to do so.
merijn 2017-03-01 05:26:47
brynser_: But I just have a simple product datatype, and storing as varchar is utterly unacceptable for my usecase
MersenneInteger 2017-03-01 05:26:55
Should Haskell be my first foray into functional programming or should I learn Scheme first and work my way up to Haskell?
merijn 2017-03-01 05:27:10
Cale: I remember a presentation at Dutch FP day on esqueleto, it seemed reasonably complete
Cale 2017-03-01 05:27:20
MersenneInteger: I'd say go for Haskell directly.
merijn 2017-03-01 05:27:25
MersenneInteger: tbh, I don't think learning Scheme first will really help much
kuribas 2017-03-01 05:27:27
merijn: I don't think it matters, except for inner loops...
kuribas 2017-03-01 05:27:44
MersenneInteger: scheme is great, but it is rather different from haskell.
brynser_ 2017-03-01 05:27:59
merijn: Oh right, not sure then, I've only done e.g. "data Foo = Bar Int | Baz Text | ..."
Cale 2017-03-01 05:29:02
If you were going to go for any lisp, I would say some scheme variation is probably the best to try to do functional programming in. Common lisp is quite annoying -- I've tried to program in a functional style in it, and you're basically swimming upstream.
kuribas 2017-03-01 05:29:09
MersenneInteger: scheme is strict, dynamic typed, and uses Lispy syntax.
Cale 2017-03-01 05:29:42
But no pattern matching is sort of... barely functional programming.
MersenneInteger 2017-03-01 05:30:23
Thanks for the answers, Ive never programmed in a functional language before so I didnt know where I should start. I considered reading SICP because I wasnt sure where to start. Where is a good (book) place to start with Haskell? Sorry for the noob questions.
Cale 2017-03-01 05:30:36
SICP is really good, yes
merijn 2017-03-01 05:31:03
Cale: oh, maybe I can get it to work by writing a PersistEntity class by hand
Tuplanolla 2017-03-01 05:31:28
Scheme is certainly less daunting to start with, MersenneInteger.
Cale 2017-03-01 05:31:41
We don't really have anything nearly as good as that specifically for Haskell, but Graham Hutton's "Programming in Haskell" is good.
Cale 2017-03-01 05:31:55
If you're looking for something freely available to start off with...
Cale 2017-03-01 05:32:07
http://www.cis.upenn.edu/~cis194/spring13/
kuribas 2017-03-01 05:32:12
MersenneInteger: SICP is great, but it isn't really about scheme, it's more about programming paradigms.
Cale 2017-03-01 05:32:24
contains a bunch of lecture notes and exercises which many people have found useful
Cale 2017-03-01 05:32:58
Yeah, reading SICP / watching the SICP lectures is a lot of fun once you know a bit of Haskell too
Cale 2017-03-01 05:33:34
Because you get to see how many of the things they talked about there have been formalised into Haskell.
Cale 2017-03-01 05:34:14
(Things which were merely conventions have gotten language support)
frostbit 2017-03-01 05:34:35
Hey
Cale 2017-03-01 05:34:40
hello!
frostbit 2017-03-01 05:34:53
can you tell me what <+> does?
merijn 2017-03-01 05:34:59
Cale: hmm, maybe not, apparently the recommend solution "hand write a conversion from persistent entiy to your own datatype" :\
Cale 2017-03-01 05:35:11
frostbit: Probably if you can tell me which library it comes from
frostbit 2017-03-01 05:35:19
I saw it in xmonad
frostbit 2017-03-01 05:35:30
I thought it was part of standard package
frostbit 2017-03-01 05:35:38
And I hadn't read it
frostbit 2017-03-01 05:35:47
so that's why tho confusion
Cale 2017-03-01 05:36:04
ah, it's infix mappend
suppi 2017-03-01 05:36:08
MersenneInteger: www.haskellbook.com is quite good from what i read. i also like this course to get familiar with fp: https://www.coursera.org/learn/programming-languages
Cale 2017-03-01 05:36:27
But specifically, in xmonad, it's used to compose together ManageHooks
suppi 2017-03-01 05:36:59
it's standard ml but the ideas you learn there transfer to other languages like haskell, ocaml, elm, etc
frostbit 2017-03-01 05:37:19
Oh right
frostbit 2017-03-01 05:37:28
I feel like a knobhead now
merijn 2017-03-01 05:38:03
bleh, this is annoying. So I can either get decent mapping of datatype to database with groundhog, or keep the ability to add/switch to esqueleto if I need joins with persistent, but not both :\
merijn 2017-03-01 05:38:22
And groundhog apparently can't stream results either
Cale 2017-03-01 05:38:41
The result of a ManageHook is an Endo WindowSet, which is just a wrapper around a function WindowSet -> WindowSet, and it basically composes those functions together.
Cale 2017-03-01 05:38:57
merijn: Everything is terrible
frostbit 2017-03-01 05:39:40
Got it thanks
Cale 2017-03-01 05:39:40
merijn: It's one of the biggest scary things to tackle on our horizon
frostbit 2017-03-01 05:39:40
\part
merijn 2017-03-01 05:39:57
Cale: honestly, since I probably don't need joins I'd be fine switching to groundhog, but the lack of streaming results kinda kills me :(
merijn 2017-03-01 05:40:32
Cale: I don't wanna get lists for queries with hundreds of thousands or more results
Cale 2017-03-01 05:41:34
Yeah, we just stick LIMIT on most things
merijn 2017-03-01 05:42:36
Cale: That doesn't work very well if you actually plan to use all those results ;)
Cale 2017-03-01 05:42:37
(If we ever have to deal with more than a handful of results at a time, something is wrong with our architecture anyway, due to the nature of our applications.)
merijn 2017-03-01 05:43:21
Right now I have all my data in...plain text files, that I munge in memory before feeding it to my code, which is killing my performance now that I've 10x increased my dataset :p
merijn 2017-03-01 05:43:35
So it's one of the main reasons to wanna dump everything in an SQLite database
merijn 2017-03-01 05:44:11
Right, so persistent + ugly manual data conversion it is, for now