lainchan / λ

Haskell, functional fun

Yuki Nagato · 2017-05-09 09:45
import System.Posix.Process main = do forkProcess (putStrLn "This is the new process") putStrLn "This is the original process" Hey lainons, why not talk a bit about Haskell? What are you working on? Do you need help? Do you have any tips for other Haskell enthusiasts?
Lady Jessica · 2017-05-10 09:41
Haskell is one of my favourite languages for quickly writing command-line tools, or for writing scripts using the Turtle library. It can be ridiculously expressive, and once you have used GADT's on any problem domain that they are well suited for, going back to a language without them is hard. Finding the cause of a performance bug can be absolute hell though.
Anamika · 2017-05-10 12:06
I started working through pic related, seems pretty nice so far, my Haskell knowledge is all over the place that why I guess working through a book will close a lot of holes. >>1039 Turtle always seemed pretty useful to me, but I have not used it so far.
Stallman · 2017-05-10 15:32
Is Haskell the 'end all be all' of these kinds of langs, or if I were to start from scratch should I move on to Idris or one of the other 'spiritual successors' of haskell?
x<->y · 2017-05-10 17:50
>>1045 > should I move on to Idris or one of the other 'spiritual successors' of haskell? Most of them actually remove the things I like most about Haskell, if we talk about stuff like Frege and such. I seems as if they try and solve nonexistent problems with Haskell. I do not see any appeal in them compared to Haskell if you want to do functional programming.
Pulse · 2017-05-10 18:00
>>1045 Haskell is probably the most practical (in terms of tooling and libraries) of its kind right now, so you should go with that if you plan on doing more than just learning the theory behind it. Because it's the most popular, it also has the best documentation (at least in terms of introductory materials). I think that it's therefore the best language to learn the ML programming paradigm with. That being said, Haskell of course isn't the non-plus-ultra of programming language design. Dependent types are great and what you can do with them is tons of fun, but the documentation just isn't that great and you can't do much apart from knowing them outside of the academical space as of now. You'll have a much easier time diving into them once you already have the basics down.
Ender · 2017-05-10 18:08
>>1048 Do you not know what Idris is? It does not at all just remove things. Idris has a dependent type system that writes very similar to haskell, and is written in haskell. The dependent type system is strictly more powerful than haskells type systems and allows the expression of more properties of types. For example the (statically verified) type of sorted lists.
Vasya Pupkin · 2017-05-10 18:09
>>1045 Haskell has far more teaching materials and a more active community. I think it is very valuable from an educational viewpoint even if you don't use it much. A research languages would be difficult to get into if you haven't encounted any ML or Haskell like language before. Regardless of what you pick though, if you learn a functional language where immutability is the norm, read Chris Okasaki's book on functional data structures. It's one of the best algorithm books around for FP, and the contents carry over to all the functional languages.
Tequila · 2017-05-10 18:10
>>1053 I just uploaded Okasaki's book on the E-book thread here: 1051
setq · 2017-05-10 18:20
>>1052 > Do you not know what Idris is? > if we talk about stuff like Frege and such I actually do not know much about Idris, thats why I chose another example.
Otto Normalverbraucher · 2017-05-10 21:16
>>1052 Idris is a child born out of incestuous relationship between Haskell and Agda.
Gyula Kovacs · 2017-05-11 00:59
I've been trying to reimplement mtl just to get a feel for how they work. So far I've only written the Writer monad, here's my code: {-# LANGUAGE FlexibleInstances, FunctionalDependencies, MultiParamTypeClasses, TupleSections #-} import Control.Arrow(first, second, (***)) class (Monad m, Monoid w) => MonadWriter w m | m -> w where tell :: w -> m () listen :: m a -> m (a,w) newtype WriterT w m a = WriterT { runWriterT :: m (a,w) } execWriterT :: Monad m => WriterT w m a -> m w execWriterT = (fmap snd) . runWriterT evalWriterT :: Monad m => WriterT w m a -> m a evalWriterT = (fmap fst) . runWriterT instance Functor m => Functor (WriterT w m) where fmap f (WriterT p) = WriterT (fmap (first f) p) instance (Applicative m, Monoid w) => Applicative (WriterT w m) where pure = WriterT . pure . (,mempty) (WriterT af) <*> (WriterT ax) = WriterT (af' <*> ax) where af' = fmap (\(f,w1) (x,w2) -> (f x, mappend w1 w2)) af instance (Monad m, Monoid w) => Monad (WriterT w m) where (WriterT mx) >>= f = WriterT (mx >>= f') where f' (x,w1) = runWriterT (f x) >>= (pure . second (mappend w1)) instance (Monad m, Monoid w) => MonadWriter w (WriterT w m) where tell = WriterT . return . ((),) listen (WriterT p) = WriterT (fmap (\(x,w) -> ((x,w),w)) p) r8. It's ugly and has been quite the case of "if it typechecks, it's probably correct"
Hopper · 2017-05-11 12:18
>>1062 I would probably write it in not such a "code golf" style. I find TupleSections more often harms readability than it helps. haskell pure a = WriterT (pure (a, mempty)) tell w = WriterT (return ((), w)) You also have some unnecessary parentheses: haskell execWriterT = fmap snd . runWriterT evalWriterT = fmap fst . runWriterT You could also relax the Monad constraint on MonadWriter to Applicative (although then the name is not really so fitting) if you use pure rather than returm.
Terzibashjian · 2017-05-15 22:34
Can anyone suggest a good read on monad transformers that explains them in terms of category theory?
Shogun · 2017-05-17 18:04
>>1176 I have just read the wikipedia page, and it looks like a functor between Kleisli categories. A Kleisli category (what Haskell improperly calls monad) has an identity function (called return in haskell) and a composition function (I can't find it in haskell, but it should be something like comp = \f -> \g -> \x -> (g x) >>= f). The so-called monad laws are actually the category laws for these special identity and composition function (identity is neutral for composition, and composition is associative). (see associativity and identity in https://en.wikipedia.org/wiki/Category_(mathematics)#Definition). Functors in Haskell are just a special case of categorical functors ("Haskell functors" are endofunctors). https://en.wikipedia.org/wiki/Functor A monad transformer (https://en.wikipedia.org/wiki/Monad_transformer) preserves the identity of Kleisli categories (if you pose F x = lift . x, then F(return) = return), and it preserves the composition of Kleisli categories (F(f `comp` g) = F(f) `comp` F(g)). It is more useful in practice not to use comp and F but bind and lift, but I have presented a mathematical view of the subject.
Unnamed · 2017-05-17 18:08
>>1039 >once you have used GADT's on any problem domain that they are well suited for What kind of "real-life" domain are GADT well-suited for?
Undisclosed · 2017-05-17 22:26
>>1176 They are just functions from monads to monads, in a way that preserve some properties. Search for the class MonadTrans to see the rules.
Hiro Protagonist · 2017-05-19 21:57
>>1230 (not >>1039) GADTs are just a great way of dealing with data which may take a type parameter but where you don't want that leaking out. GADTs are existential types + equality constraints. For example, I have a little library for testing concurrent things, and it can either test something randomly, or exhaustively. Exhaustive testing might be slow, so the random testing is there for people who prefer to sacrifice certainty for time. I use (something like) this type to represent "the way of testing a concurrent thing": haskell data Way where Exhaustive :: Way Random :: RandomGen g => g -> Way Originally, I just used a regular sum type like so: haskell data Way g = Exhaustive | Random g But that has a pretty significant problem: what is the type of Exhaustive? The g type parameter isn't determined by anything, so you get ambiguous type errors, and end up needing to fix it to some concrete type even though it's not used. The GADT version is strictly better because it doesn't have that issue, and it can even enforce the constraint that the g type is a RandomGen.
emph · 2017-05-20 01:44
>>1286 This pattern of encapsulating a type variable in a single variant of the GADT is one of the most useful, IMO. You get ad-hoc polymorphism, which is basically one of the selling points of OO. Here's how I've applied it in the past: Let's say I'm building a language. I start with the usual declarations: data Expr = EInt Integer -- integer literal | EVar String -- variable | ELam String Expr -- lambda function | EApp Expr Expr -- application data Val = VInt Integer -- integer value | VFun (Val -> Val) -- function eval :: [(String,Val)] -> Expr -> Val eval = -- implementation: https://ghostbin.com/paste/udh2j But let's say I want to define new expression types, without having to change my definition of Expr and eval. How can I do this? Well, you can first split each kind of Expr into its own type, and then make eval a typeclass: class Expr e where eval :: [(String,Val)] -> e -> Val data Val = VInt Integer -- integer value | VFun (Val -> Val) -- function data EInt = Int Integer -- integer literal data EVar = Var String -- variable data ELam = Lam String Expr -- lambda function data EApp = App Expr Expr -- application Now of couse this doesn't compile, since we're trying to use Expr as a type when in fact it's a typeclass. We fix this by parameterizing our new types: data EInt = Int Integer -- integer literal data EVar = Var String -- variable data ELam e = Lam String e -- lambda function data EApp e1 e2 = App e1 e2 -- application instance Expr EInt where ... instance Expr e => Expr (ELam e) where -- implementation: https://ghostbin.com/paste/22z6s This works, and allows us to arbitrarily add new expressions just by creating new types an implementing the typeclass. But now the problem is that we can't read an arbitrary expression from user input, since expressions have to be of some compile-time known type. In fact, we can't even create a list of expressions: λ> [Int 3, Var "x"] -- ERROR We solve this by creating a super simple GADT, like so: data AnyExpr where E :: Expr e => e -> AnyExpr instance Expr AnyExpr where eval ctx (E expr) = eval ctx expr We can now use the AnyExpr type when either the specific type is only dynamically available, or we purposely don't care about the exact kind of expression. The helpful property still holds, that we can create new expressions without modifying the definition of Expr. [E (Int 3), E (Var "x")] :: [AnyExpr] Here's the full code with a shoddy parser thrown in: https://ghostbin.com/paste/has33 There are other interesting properties of implementing a language this way, which you really can't achieve easily in many other languages. I can explain if anyone is interested.
Marly Krushkhova · 2017-05-21 12:22
The most important performance tip I can give to any newish Haskell programmer: use sequences instead of lists unless you really need a linked list or laziness. ( https://hackage.haskell.org/package/containers-0.5.10.2/docs/Data-Sequence.html ). This is very important. Just like in Lisp, linked lists are often the main reason why Haskell code is slow.
Jens Hansen · 2017-05-21 14:07
>>1332 As with all things, it depends. Sequences have higher constant factors than lists, and if you're using a list to store some collection of intermediary values, GHC may well fuse the surrounding computation and result in the list never being allocated fully (or even at all) in memory. I would hesitate to use a sequence over a list before profiling. GHC has some pretty good tools for profiling[1] time and space. You can get a simple execution profile like so (if you're using Stack, Cabal and plain GHC also have flags to build with profiling): $ stack build --profile $ stack exec -- dejafu-tests +RTS -p $ less dejafu-tests.prof Which gives you a report like Mon Mar 20 19:26 2017 Time and Allocation Profiling Report (Final) dejafu-tests +RTS -p -RTS total time = 105.94 secs (105938 ticks @ 1000 us, 1 processor) total alloc = 46,641,766,952 bytes (excludes profiling overheads) COST CENTRE MODULE %time %alloc findBacktrackSteps.doBacktrack.idxs' Test.DejaFu.SCT.Internal 21.9 12.0 == Test.DejaFu.Common 12.4 0.0 yieldCount.go Test.DejaFu.SCT 12.1 0.0 dependent' Test.DejaFu.SCT 5.1 0.0 runThreads.go Test.DejaFu.Conc.Internal 2.7 4.1 [...] There's also heap profiling (in [1]), which can show you where your memory is going and what types are using it (which can often be more helpful, in my experience, than just knowing which functions are doing the allocation, and really clearly shows space leaks), and ThreadScope[2] for concurrency and CPU time. [1] https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html [2] https://wiki.haskell.org/ThreadScope
Turing · 2017-05-21 17:10
>>1334 Right, you use lists when you want laziness, which includes most cases where you would use iterators or streams in a procedural language. But if you're going to do anything like concatenating, slicing, or doing random access, lists are horrible. There's the classical case of the sieve of eratosthenes, which is trivial to implement in O(n log(n) log(log(n)) ) with sequences, while afaik there is no algorithm that beats trial divison by more than a constant factor using only lists.
Dozer · 2017-05-22 22:12
Does anyone here have recommendation for a Haskell GUI? I've gotten reasonably far with Haskell and I'd like to try making stuff with it.
() · 2017-05-23 17:19
>>1407 There are GTK, QT, OpenGL and FLTK bindings. Another option is to use HTML + JS via threepenny or indirectly via GHCJS and Reflex..
roll · 2017-05-23 17:22
>>1350 A good summary is that lists are good intermediate types, for passing data around, but bad for storage and retrieval of data.
drop · 2017-05-24 02:13
>>1429 Another way of saying that, which I've heard elsewhere, is that in Haskell we use lists for control flow.
Marly Krushkhova · 2017-05-24 18:47
>>1041 Have you tried Haskell Programming from First Principles(http://haskellbook.com/)?
Zhora · 2017-05-24 18:49
>>1045 Dependent types are cool and what you can hypothetically accomplish is great. But the way Idris implements dependent types essentiall requires a PHD to write useful programs.
Boris Grishenko · 2017-05-25 10:47
>>1439 Yes I have, I worked with it when it was in early stages back several months ago. After reading up to chapter 2, I prefer the Manning book as it seems a bit more concise and better suited for me. Haskell Programming from First Principles still appeared to be very good and I will probably read through specific chapters when I'm finished.
Moore · 2017-05-26 00:58
New to Haskell, coming from C and C++ What's the performance hit like? It seems like there'd be a lot of memory overhead and extra cycles, how do you go about optimising programs and how would they compare to C(++)?
Cat Mother · 2017-05-26 07:39
>>1454 C and C++ programmers seem to think they are avoiding 'overhead' because they are manually managing memory. People who think this dont understand how compilers work. Haskell compiles to binaries just like C and C++ and less than bright people might think that all the language abstractions somehow are compiled into the binary. What they dont understand is that Haskell's abstractions allows it to do a lot of optimizations that are not possible in C or C++. The benchmarks for Haskell vs C/C++ can be found by googling, Haskell gets very close to C/C++ and surpasses it in certain situations. There might have been an argument for using C back when most computers had 68k of memory, but now that is a non-issue now.
Linda Lee · 2017-05-26 13:40
>>1454 It's difficult to compare. They'll perform similarly if you use the same algorithms. In practice though, you will almost never use the same algorithms in a Haskell program as you would in C++, except for some very specific problems. This is because the standard data structures you reach for are different. Getting a proper introduction to immutable data structures and functional algorithms that act on those is important when migrating to any functional language. There is a lot of very poorly written Haskell code out there that performs horribly because the writer isn't aware of the asymptotic time and memory complexity of his code.
Jean Dupont · 2017-05-26 17:36
>>1286 Barrucadu identified ;) >>1458 The faster than C stuff is difficult to verify, since you can always write the same in C. I think the most honest anwer to the performance question is to say it is Java-like. Typed and compiled.
emphasis · 2017-06-04 19:28
I've been thinking a bit about monads, and I've decided that "join" is much more clear and elegant as a defining monadic operation than "bind". join is very symmetric, class Monad m where return :: a -> m a join :: m (m a) -> m a Here we see that `return` wraps a value, and `join` unwraps a doubly-wrapped value. Functor cannot do the former, and Applicative cannot do the latter. The monad law then follows from the type signatures: join (return (return x)) = return x Also, it's VERY easy to implement fundamental monads. -- list instance Monad [] where return x = [x] join = concat -- either instance Monad (Either e) where return = Right join (Left x) = Left x join (Right y) = y -- reader instance Monad ((->) r) where return = const join f x = f x x -- writer instance Monoid w => Monad ((,) w) where return x = (mempty, x) join (w1, (w2, x)) = (w1 <> w2, x) -- identity instance Monad Identity where return = Identity join = runIdentity Then of course we can implement `bind` using `fmap` and `join` bind x f = join (f <$> x) What do you think? Does (>>=) capture the notion of a monad better, even though it is more difficult to understand / implement instances of? Are there other advantages / disadvantages I haven't thought of?
Trinity · 2017-06-04 21:10
>>1630 I agree that for some monads (like the ones you listed), defining it via join is much more intuitive. There are of course also monads where the bind definition is easier (like State, Continuation or parser monads). I think knowing both ways to look at monads well is very helpful when thinking about them. One problem with thinking about monads via join is that joining isn't really what you're doing with them in Haskell. The do-syntax is pretty much all you use and that's binding, so you need to have a good intuition about what bind does none the less (though you can acquire that by thinking about `join . map f`).
Arisu Mizuki · 2017-06-06 12:06
>>1630 That's precisely how cat theory describes monads, and I absolutely agree with you that it's a lot more intuitive than using bind.
The Phantom Phreak · 2017-06-15 03:10
I had a really neat Haskell idea at 3am a few nights ago, so I wrote it up and later revised it so that interested lainons can read over it. Consider it trying my hand at "literate programming". Basically the idea is this: when making a interpreter in Haskell, attach a type parameter to the data for the target language's types, which refers to the representation of that type in the host language (Haskell). This is only possible with some advanced GADT shenanigans: data Typ h where TInt :: Typ Integer TBool :: Typ Bool TPair :: Typ h -> Typ j -> Typ (h, j) TFun :: Typ h -> Typ j -> Typ (h -> j) typShow :: Typ h -> (h -> String) typShow TInt n = show n typShow TBool True = "tru" typShow TBool False = "fal" typShow (TPair a b) (x,y) = "(" ++ typShow a x ++ "," ++ typShow b y ++ ")" typShow (TFun a b) f = "<function>" subtype :: Typ h -> Typ j -> Maybe (h -> j) subtype TInt TBool = Just (\n -> n /= 0) subtype TInt TInt = Just id subtype TBool TBool = Just id subtype (TPair a b) (TPair c d) = do sub1 <- subtype a c sub2 <- subtype b d Just (\(x,y) -> (sub1 x, sub2 y)) subtype (TFun a b) (TFun c d) = do subArg <- subtype c a subRet <- subtype b d Just (\f x -> subRet (f (subArg x))) subtype _ _ = Nothing The full source is here: https://ghostbin.com/paste/o8oqz It's 300 lines of heavily commented Haskell code. For tl;dr, see the examples at the very bottom. But please read it and tell me what you think. λ> compileAndRun (4 `eq` 4) tru : Bool λ> compileAndRun $ ELet "x" 3 (vx * vx - 4) 5 : Int λ> compileAndRun $ ELet2 "x" "y" (EPair 3 4) (vx * vy) 12 : Int λ> compileAndRun $ lam "x" TInt (vx `eq` 0) <function> : Int → Bool λ> compileAndRun $ app (lam "x" TInt (vx `eq` 0)) 1 fal : Bool λ> compileAndRun (4 `eq` tru) invalid argument, expected Int, got Bool λ> compileAndRun $ app (lam "x" TBool (vx `pair` vx)) 1 (tru,tru) : Bool × Bool -- subtyping behavior
Agent Jones · 2017-06-17 01:57
>>1458 http://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=ghc&lang2=gcc this shows haskell performing 2 to 10 times worse than c
Ein · 2017-06-17 17:02
>>1842 Yeah, idiomatic haskell is quite slow. I remember there was a benchmark suite, (https://www.techempower.com/benchmarks/ ), where one of the web frameworks (yesod iirc) asked to be removed from the benchmarks after they came out half as fast as ruby on rails or something. Techempower refused btw
Splicer · 2017-06-18 04:15
>>1863 I've seen people optimize Haskell quite tightly without using some DSL but it's super weird to optimize. Like optimization is just...different in functional languages. So idiomatic Haskell is slow Haskell.
Incognito · 2017-06-18 22:02
>>1842 The Haskell code in that benchmark is quite unidiomatic though, to the point of giving almost no indication of how well or poorly idiomatic Haskell fares. It's basically C written in Haskell. Which can be significantly faster, or significantly slower, depending on compiler optimizations.
Chani · 2017-06-19 17:07
I was discussing performance in Haskell with someone on IRC and its very non-obvious when a Haskell program will or won't blow up, and you can't always rely on GHC being a "sufficiently smart compiler". For instance niterate :: (a -> a) -> a -> Integer -> a niterate f z 0 = z niterate f z n = niterate f (f z) (n - 1) main :: IO () main = print (niterate (+ 5) 0 100000000) In a "normal" FP language like Ocaml or Scheme, this would be able to handle the large argument, because it uses tail position and only performs simple arithmetic. However this blows up and uses gigabytes of memory in Haskell, unless you enable an extension and change the third line to niterate f !z n = niterate f (f z) (n - 1)
roll · 2017-06-20 22:08
>>1863 Haskell is slow, but not too slow. What matters is correctness, and developer time, Haskell saves that for me, and I will gladly trade of the performance loss. Haskell + Nix make it more of an even enjoyable experience. (Stack is rubbish to me, even with Nix integration, it just clashes hard with Cabal.) Idiomatic or unidiomatic not, Haskell suffers from literally only having one modern implementation which is GHC, and that suffers from a poorly implemented garbage collector algorithm. Also the performance penalty of strings in Haskell is ridiculous. Now, onto the techempower benchmarks, there doing non-equivalent comparisons. For example servant was more implemented to the IETF RFCs than the Go implementation last I checked.
Lord Nikon · 2017-07-03 05:29
>>1910 What does !z in niterate !z n do? >>1931 I agree on stack being rather obtuse
Wirth · 2017-07-04 21:42
>>2153 >What does !z in niterate !z n do? It makes that argument be strictly evaluated, instead of lazy. Without the !, the second argument of niterate would build up a huge chain of (f (f (f ... (f (f 0))...))) that only gets evaluated on the last recursive call, but with the !, each call of niterate would actually find out what (f z) is before passing it to the next call.
bit · 2017-07-08 03:53
Is there a more modern equivalent to Happy? Preferably one that doesn't require a seperate file and build tool
Tequila · 2017-07-09 12:09
>>2228 Parser combinators? Happy is a Haskell equivalent of flex/yacc, so it works in a similar way to those venerable tools.
Lain Iwakura · 2017-07-09 14:50
>main languages currently are c++/c/python >have no knowledge of Haskell People have been telling me that Haskell is the key to understanding programming better. Any reasons? Should anyone pick it up?
Nell · 2017-07-09 15:12
>>2249 I mean where you specify a grammar and it figures it out for you
Incognito · 2017-07-09 15:21
>>2251 Haskell is a great FP language with an excellent type system. FP languages have often been close to the development of the theory of programming languages. Haskell is pure, and represents effects mostly by using monads. In many situations it is very concise (except when writing very imperative or bitwise code) and you could (if you wanted) easily write very impressive EDSLs. Learning Haskell is mostly about learning how to use a strongly typed pure functional language, learning a variety of type constructs (some brought over from category theory), and learning how to use certain type features to build those constructs. As other languages increasingly adopt strong typing and FP features, Haskell knowledge becomes increasingly transferable. Alternatives to Haskell include Idris (though it's relatively new), OCaml (though it isn't pure) and purescript (though it targets javascript).
Hiro Protagonist · 2017-07-09 15:23
>>2251 It's not necessarily due to something inherently unique to Haskell, as it is about learning a statically typed functional language with a decent type system. Among the languages that tick these boxes Haskell is among the most mature, and unlike the runner-up options it is opinionated enough to force you into writing pure functional code with no side effects, which is good for learning to write functional code without using any escape hatches.
Apoc · 2017-08-12 21:48
https://gergo.erdi.hu/projects/icfp-bingo-2017//
Miho Iwakura · 2017-08-12 23:32
I have to say I really love Parser combinors. They were the application that really made me realize how powerful monads can be.
fsociety · 2017-08-14 06:25
>>2902 This is gold, thank you. I'm going to ICFP for the PLMW in September. I can't wait to hear all about linear types and induction over natural numbers
vector · 2017-08-17 09:13
can someone improve this unholy mess? Base64 -> binary , binary -> Base64 converter. I'm new to haskell. sixfourtwo :: Char -> String sixfourtwo x | x == 'A' = "000000" | x == 'B' = "000001" | x == 'C' = "000010" | x == 'D' = "000011" | x == 'E' = "000100" | x == 'F' = "000101" | x == 'G' = "000110" | x == 'H' = "000111" | x == 'I' = "001000" | x == 'J' = "001001" | x == 'K' = "001010" | x == 'L' = "001011" | x == 'M' = "001100" | x == 'N' = "001101" | x == 'O' = "001110" | x == 'P' = "001111" | x == 'Q' = "010000" | x == 'R' = "010001" | x == 'S' = "010010" | x == 'T' = "010011" | x == 'U' = "010100" | x == 'V' = "010101" | x == 'W' = "010110" | x == 'X' = "010111" | x == 'Y' = "011000" | x == 'Z' = "011001" | x == 'a' = "011010" | x == 'b' = "011011" | x == 'c' = "011100" | x == 'd' = "011101" | x == 'e' = "011110" | x == 'f' = "011111" | x == 'g' = "100000" | x == 'h' = "100001" | x == 'i' = "100010" | x == 'j' = "100011" | x == 'k' = "100100" | x == 'l' = "100101" | x == 'm' = "100110" | x == 'n' = "100111" | x == 'o' = "101000" | x == 'p' = "101001" | x == 'q' = "101010" | x == 'r' = "101011" | x == 's' = "101100" | x == 't' = "101101" | x == 'u' = "101110" | x == 'v' = "101111" | x == 'w' = "110000" | x == 'x' = "110001" | x == 'y' = "110010" | x == 'z' = "110011" | x == '0' = "110100" | x == '1' = "110101" | x == '2' = "110110" | x == '3' = "110111" | x == '4' = "111000" | x == '5' = "111001" | x == '6' = "111010" | x == '7' = "111011" | x == '8' = "111100" | x == '9' = "111101" | x == '+' = "111110" | x == '/' = "111111" | otherwise = return x sixfourtwoparse :: String -> String --sixfourtwoparse [] = [] --sixfourtwoparse ( x : xs ) = ( sixfourtwo ( x ) ) ++ ( sixfourtwoparse ( xs )) sixfourtwoparse x = concat $ map sixfourtwo x twosixfour :: String -> Char twosixfour x | x == "000000" = 'A' | x == "000001" = 'B' | x == "000010" = 'C' | x == "000011" = 'D' | x == "000100" = 'E' | x == "000101" = 'F' | x == "000110" = 'G' | x == "000111" = 'H' | x == "001000" = 'I' | x == "001001" = 'J' | x == "001010" = 'K' | x == "001011" = 'L' | x == "001100" = 'M' | x == "001101" = 'N' | x == "001110" = 'O' | x == "001111" = 'P' | x == "010000" = 'Q' | x == "010001" = 'R' | x == "010010" = 'S' | x == "010011" = 'T' | x == "010100" = 'U' | x == "010101" = 'V' | x == "010110" = 'W' | x == "010111" = 'X' | x == "011000" = 'Y' | x == "011001" = 'Z' | x == "011010" = 'a' | x == "011011" = 'b' | x == "011100" = 'c' | x == "011101" = 'd' | x == "011110" = 'e' | x == "011111" = 'f' | x == "100000" = 'g' | x == "100001" = 'h' | x == "100010" = 'i' | x == "100011" = 'j' | x == "100100" = 'k' | x == "100101" = 'l' | x == "100110" = 'm' | x == "100111" = 'n' | x == "101000" = 'o' | x == "101001" = 'p' | x == "101010" = 'q' | x == "101011" = 'r' | x == "101100" = 's' | x == "101101" = 't' | x == "101110" = 'u' | x == "101111" = 'v' | x == "110000" = 'w' | x == "110001" = 'x' | x == "110010" = 'y' | x == "110011" = 'z' | x == "110100" = '0' | x == "110101" = '1' | x == "110110" = '2' | x == "110111" = '3' | x == "111000" = '4' | x == "111001" = '5' | x == "111010" = '6' | x == "111011" = '7' | x == "111100" = '8' | x == "111101" = '9' | x == "111110" = '+' | x == "111111" = '/' | otherwise = 'X' twosixfourparse :: String -> String twosixfourparse [] = [] twosixfourparse x = ( twosixfour $ take 6 x ) : ( twosixfourparse $ drop 6 x )
Mario Rossi · 2017-08-17 11:08
>>2956 convert to int (fromEnum) check if it's in 'A'..'Z' or 'a'..'z' (also converted to int) change the number appropriately, e.g. subtract 'A' and if it's in 'a'..'z' then subtract the difference between 'Z' and 'a' convert that final int to bits
Emmanuel · 2017-08-17 11:24
>>2956 >>2957 charInt :: Char -> Maybe Int charInt '+' = Just 62 charInt '/' = Just 63 charInt c | inr 'A' 'Z' = fun 00 'A' | inr 'a' 'z' = fun 26 'a' | inr '0' '9' = fun 52 '0' | otherwise = Nothing where inr l h = c >= l && c <= h fun d x = Just (d + fromEnum c - fromEnum x) intChar :: Int -> Maybe Char intChar 62 = Just '+' intChar 63 = Just '/' intChar i | inr 0 25 = fun 00 'A' | inr 26 51 = fun 26 'a' | inr 52 61 = fun 52 '0' | otherwise = Nothing where inr l h = i >= l && i <= h fun d c = Just (toEnum ((i - d) + fromEnum c)) now just write something that converts int to and from binary
Nobody important · 2017-08-22 20:26
{-# LANGUAGE PolyKinds, TypeFamilies, RankNTypes, FlexibleInstances #-} -- -XPolyKinds -XTypeFamilies -XRankNTypes -XFlexibleInstances import Data.Functor.Identity import Data.Functor.Compose import Control.Monad import Control.Comonad data Natural f g = Natural { getNatural :: forall a. f a -> g a } class Comonoid m where comappend :: m -> (m, m) comempty :: a -> () comempty = const () class Monoidal (m :: k) where type Product m :: k -> k -> k type Exponen m :: k -> k -> * type Identit m :: k memptyLike :: (Exponen m) (Identit m) m mapendLike :: (Exponen m) ((Product m) m m) m class Comonoidal (m :: k) where type Product m :: k -> k -> k type Exponen m :: k -> k -> * type Identit m :: k comemptyLike :: (Exponen m) m (Identit m) comapendLike :: (Exponen m) m ((Product m) m m) instance Monoid m => Monoidal m where type Product m = (,) type Exponen m = (->) type Identit m = () memptyLike = const mempty mapendLike = uncurry mappend instance Monad m => Monoidal m where type Product m = Compose type Exponen m = Natural type Identit m = Identity memptyLike = Natural (return . runIdentity) mapendLike = Natural (join . getCompose ) instance Comonoid m => Comonoidal m where type Product m = (,) type Exponen m = (->) type Identit m = () comemptyLike = comempty comapendLike = comappend instance Comonad m => Comonoidal m where type Product m = Compose type Exponen m = Natural type Identit m = Identity
Splicer · 2017-08-22 20:30
>>3009 tl;dnr version class Monoidal (m :: k) where type Product m :: k -> k -> k type Exponen m :: k -> k -> * type Identit m :: k -- pseudo syntax let type (~>) = Exponen m let type (*) = Product m let type I = Identit m memptyLike :: I ~> m mapendLike :: (m * m) ~> m instance Monoid m => Monoidal m instance Monad m => Monoidal m
Chan Siu Ming · 2017-08-23 15:31
>>3009 in retrospect I'm not sure why I can define those associated types for both Monoidal and Comonoidal
John Peters, You Know, The Farmer · 2017-09-11 23:56
>>1012 Hello, Lains! I'm using the "Haskell Programming from First Principles" book to learn Haskell and while I'm enjoying it so far, I'm finding the data type -creation syntax a bit confusing. For example, the book uses these types of data declarations: data Identity a = Identity a Which at least intuitively makes sense... Then you have things like: data TisAnInteger = TisAn Integer --Example 1 data StringOrInt = -- Example 2 TisAnInt Int | TisAString String In Example 1, does this mean that TisAnInteger has one field, which is an integer? if so, what does "TisAn" do? Is that the name of the variable? In Example2, I have the same question, but what does the pipe sign do? Isn't that supposed to be a "guard" using functions? Is this doing the equivalent of a "union" type in C? Thanks in advance!
Chani · 2017-09-12 05:04
What the fuarrrk is all this fancy code. Also, can we settle which language "makes you a better programmer," Lisp or Haskell?
car · 2017-09-12 12:14
>>3425 In the first example, you're creating a data type called TisAnInteger, which has one "constructor" named TisAn, which has an Integer field. Thus, you can create a TisAnInteger by saying e.g. TisAn 4. In the second example, your data type has two different constructors: TisAnInt and TisAString. This means that StringOrInt has two different representations, one with an Integer field and one with a String. Examples of StringOrInt objects could be TisAnInt 89 or TisAString "hi". This is more akin to C unions, but you might not find it very helpful to make any more analogies to C. The pipe used in data definitions doesnt have anything to do with the pipe as a "guard"; its used here because thats the same notation used in math.
Bobby Newmark · 2017-09-12 12:25
>>3429 Every decent language gives insights. The way Haskell "helps" you become a better programmer is by forcefully encouraging you to stop mutating state. Lisp shows you that programs are just data, and can be manipulated and reasoned about as such. Also, that most problems are just language problems. However, I've been soaked in functional programming for so long, I don't remember what it's like not to understand many of the things I've learned from Lisp and Haskell. These days I've been disenfranchised by much of Haskell's idioms; I don't think the hyper-generality of the standard typeclasses is very useful and I don't think lazy eval is a good thing.
Meddler · 2017-10-01 10:16
Has anyone ever made a dialect of Haskell that uses regular I/O instead of monads and doesnt force lazy evaluation?
over · 2017-10-01 10:30
>>3912 Haskell is just an ML dialect with monadic IO and lazy evaluation so maybe just OCaml/sml.
Six · 2017-10-01 10:32
>>3913 that what I thought, thx
Neo · 2017-10-01 17:07
>>3433 Why are you using Pascal style type names, like with T in front of everything?
Jens Hansen · 2017-10-09 19:10
https://github.com/ghc/ghc/blob/master/libraries/ghc-prim/GHC/Tuple.hs
Morpheus · 2017-10-09 21:24
>>4217 Surprised? That's how most languages do it.
Y.T · 2017-10-09 21:24
>>4217 jesus christ what the fuarrrk
Haruyoshi · 2017-10-10 05:47
>>4217 https://github.com/ghc/ghc/blob/master/libraries/ghc-prim/GHC/Tuple.hs#L170
dup · 2017-10-10 15:30
>>4233 When valid code can segfault a language that doesn't have pointers, that's a problem
Chan Siu Ming · 2017-10-10 16:19
>>4245 That comment line dates back from 2001, in the early days of GHC when it was just a prototype. Modern GHC lets you declare longer tuples just fine.
Anonymous · 2017-10-19 03:05
I'm working on a (2D RPG roguelike-inspired) game to teach myself Haskell. It's quite something, that language. Last thing I groked was GADTs. It's very fun. It's also very hard because there are no single package libraries for gamedev that are not FRP (and I want to click more basic concepts before I go onto that even though I do understand pipes and concurrent pipes). I'm working with Gloss. Implementing text display with any font was hard. Implementing sound and music play was hard. Implementing a console that diplays text and stays updated was hard. I really love it, I might spend too much time on it.
JARGON · 2017-11-05 17:16
Has anyone tried Agda? I'm curious to how it compared to other pure languages
Agent Richard Gill · 2017-11-18 14:09
Is learnyouahaskell really all that good? It doesn't seem to really explain functional programming too well.
Crazy Jake · 2017-11-19 07:19
>>5086 try this https://github.com/bitemyapp/learnhaskell . I just did the courses, I feel that it has given me a strong base to understand the ideas behind haskell. I did this before the guy wrote his book or whatever so I can't recommend it first hand.
Neo · 2017-11-22 12:13
Just found this really amazing resource: https://cstheory.stackexchange.com/questions/1539/whats-new-in-purely-functional-data-structures-since-okasaki
word · 2017-11-22 12:27
>>5204 One data structure that I found particularly interesting: https://infoscience.epfl.ch/record/169879/files/RMTrees.pdf
John Titor · 2017-12-30 02:54
>>1041 https://www.manning.com/books/get-programming-with-haskell is this the updated version? anyone got this?
Frank Garza · 2018-04-18 12:06
>>3425 >I'm using the "Haskell Programming from First Principles" Can anyone upload this book please?
McCarthy · 2018-04-18 13:45
>>7934 libgen.io
Special Agent Bob · 2018-04-20 15:34
>>7935 Thanks friend :)
John Peters, You Know, the Farmer · 2018-04-26 17:49
I'm trying to learn Data Structures with Haskell, and I'm absolutely confused by how to make circular linked lists. In this tutorial, https://wiki.haskell.org/Tying_the_Knot They give code to how to write it, which I'll copy+paste below data DList a = DLNode (DList a) a (DList a) --Create a doubly linked list mkDList :: [a] -> DList a mkDList [] = error "Your list must have at least one element" mkDList xs = let (first, last) = go last xs first in first where go :: DList a -> [a] -> DList a -> (DList a, DList a) go prev [] next = (next, prev) -- go prev (x : xs) next = let this = DLNode prev x rest --I have no idea what this does --How can you have rest and last reference each other if you haven't defined them? (rest,last) = go this xs next in (this, last) Is the attached picture a good way of looking at it? I'm just have a *lot* of trouble understanding the recursive definition and lazy evaluation. I also don't really know how I would "Add" a node to this data structure, whereas in C or C++ I'd just do CList insertNewNode(CList head, CNode toInsert) //hoping I didn't screw up { CNode startOfList = head->CNode; //the start of the list is relative, of course CNode endOfList = startOfList->prev; //Choose two nodes to place the new node //Set the new endpoint to be toInsert endOfList->next = toInsert; toInsert->next = startOfList; //Have the starting point be pointing backwards to the new node startOfList->prev = toInsert; toInsert->prev = endOfList; } And related question... How would I make a (simpler) one-sided circular list in Haskell? I know the general structure to convert a list to a linked list (even though arrays in Haskell are implemented as LLs) is data LinkedList a = (LLNode a) (LinkedList a) insertAtFront :: a -> LinkedList a -> LinkedList a insertAtFront toInsert oldList = (LinkedList toInsert oldList) --Hope I got the syntax right But I'm not sure where the "wrapping around" would happen, or how I would even implement it (or hell, how I would add something to the data structures. I know Haskell doesn't have a *state* per se, but I'm still confused how it implements data structures such as trees)
Iverson · 2018-04-27 03:19
>>8034 >let this = DLNode prev x rest --I have no idea what this does It constructs a new node whose left neighbor is whatever was passed in to go as prev, and whose right neighbor is the first component of the result of the go invocation given below. >--How can you have rest and last reference each other if you haven't defined them? Because >let (first, last) = go last xs first the top level go call was given its own output in the argument list. Ponder this for a moment if you're coming from the likes of C. >I also don't really know how I would "Add" a node to this data structure You would need a new node to hold the new value. This new node would need left and right neighbors that point to it. The old nodes cannot have their left and right pointers mutated in place, so new neighbors have to be built. These new neighbors have to be pointed to by their other neighbors. This propagates out from the new node throughout the entire structure, with the effect that the entire list is rebuilt. It's equivalent to extracting all values from the DList, adjoining the new value and calling mkDList, except that these can be combined into a single pass. >How would I make a (simpler) one-sided circular list in Haskell? You would pass in the final result to the top level call of a go-like builder function as a next node argument. >--Hope I got the syntax right You have two sets of bogus parens, and you meant to use LLNode in insertAtFront. >how I would add something to the data structures Adding to the single linked circular list would also result in a rebuild. >how it implements data structures such as trees Trees with parent links have links that can be strictly partitioned into disjoint classes such that no class contains circularity on its own. You cannot get back to a leaf by following parent links, and you cannot get back to the root by following child links. As a consequence trees do not require the result-as-an-argument trick. Construct the current node with the parent that was passed into the builder function and with yet-to-be-built children, then have these children be the result of calling the builder function with the newly constructed node as parent argument.
Laughing Cavalier · 2018-06-08 01:04
I was wondering what a good first project to get into Haskell would be. I want something that can really take advantage of the power of functional programming. For instance, a friend of mine did a project that simulated lens systems, and it seemed like the perfect task to get into the language, seeing as it involves chaining together systems of equations, and evaluating them all dynamically. I can't think of anything like that, though.
Morpheus · 2018-06-08 04:41
>>8772 A very practical use case of Haskell, that I use even for my hobby projects, is creating interpreters or even compilers for made up (or not) programming languages. Haskell can describe AST very seamlessly, additionally there are very good parsing libraries (e.g. parsec).
JARGON · 2018-06-08 06:24
>>8773 (not OP) See, I know that Haskell is good for parsers, but I often have a hard time using it for that. I always feel like I'm in this middle state where the parser I need is either too simple for for something like parsec, or on the other hand I should really be writing a formal grammar and using something like bison.
Rick Deckard · 2018-06-08 06:36
>>8774 I don't really think something can be too simple for parsec, I used it for really simple things (AST had literally two possible nodes) and it only needs a very minimal setup. Though bison could indeed be a better solution in some cases. Even despite that, the real breeze in Haskell is writing the AST definition and manipulating it, I heard that Haskell is good for AST and IR optimization as well, but I don't really have much experience in that. The only thing that annoys me in Haskell is probably that combining multiple monads is not exactly an easy task.
Cutter · 2018-06-08 07:07
>>8775 So the projects I often want to use parser are in "gee it would be nice to parse X languages AST for this bad pattern." Or on the other side: I want to write a microDSL with very little grammar. I guess parsec is fine for the 2nd one.
Guthrie · 2018-06-19 09:42
Should I learn Category Theory in order to be a good haskeller/scaler?
Jim Hilger · 2018-07-03 18:16
>>9065 Absolutely. Even more you should learn category theory because it's an interesting field.
DavidGaβrieλ · 2018-07-04 19:16
I start learning about haskell and I actually like it. but not as my love to Lisp. it is pretty lang and one of the best desgin PL. so yeah cheer
Terzibashjian · 2019-01-23 21:17
>>9065 I don't think it's necessary for getting better at Haskell. It is a very interesting subject though. >>8779 You could parse the 1st and do generative programming by parsing some syntax and transforming it on your end.... Basically a poor man's lisp Who here has used phantom types for anything interesting?
Pulse · 2019-01-24 00:07
>>9065 you really don't need to learn category theory as-it's-taught-from-math-books, because there it's most used as machinery for abstract algebra which is only tangentially related to haskell programming. Just learn about haskell's type system, you'll pick up exactly as much category theory as is useful to write haskell. If you're interested from a more abstract type theory perspective and not just haskell, absolutely category theory is a great thing to know.
Armitage · 2019-02-18 02:27
>>9294 there are criticisms of lisp that are legitimate
let · 2019-03-13 02:45
question: Is Yampa actually worth learning? It seems like the goal of the library is to tie Functional Reactive Programming together with a bunch of standard backends for things like graphics and networking using this weird arrow notation that I can't wrap my head around. Is there something with a nicer syntax or is this as good as it gets?
drop · 2019-03-13 08:16
>>12828 https://github.com/gelisam/frp-zoo
Just another Random Lainon · 2019-04-05 04:36
>>9065 Rather than tell you why you should or not, here's an interesting book on the subject. Let your own motivation to read it decide for you. https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/
vector · 2019-04-12 00:04
Are there are tutorials on learning how to write a game in Haskell that doesn't dive straight into graphical applications? I just want to learn the FRP or whatever equivalent of writing a text based combat game or something that has """state""". If I can't learn how to do something like this, I'm going to have to go back to dirty imperative languages.
Special Agent Bob · 2019-04-12 15:38
>>13188 Frp is just a nice technique. You could just host your state in a state monad and functionally modify that. Or use a ref and do some IO. FRP seems very nice to learn, but is not needed for passing and "mutating" state.
Joey · 2019-04-12 23:30
thoughts?
t · 2019-04-14 18:17
>>13188 What is the Haskell-way of writing code like this? class Person: name = "" age = "18" health = 10 damage = 3 def attack(self, enemy): enemy.health = enemy.health - self.damage print(self.name + " attacks the enemy." + " The enemy " + enemy.name + " has " + str(enemy.health) + " health remaining.") playerOne = Person() playerOne.name = "Player One" playerOne.age = "65" playerOne.health = 20 playerOne.damage = 2
Lunch · 2019-04-14 19:53
>>13222 monoids and soykaf.
sizeof · 2019-04-14 23:28
>>13222 Something like this. data Person = Person { name :: String , age :: Int , health :: Int, damage :: Int } deriving (Show) attack :: Person -> Person -> Person attack person enemy = enemy { health = (health enemy) - (damage person) } playerOne = Person { name = "Player One", age = 65, health = 20, damage = 2 } enemyOne = Person { name = "Enemy", age = 2, health = 5, damage = 2 } -- *Main> playerOne -- Person {name = "Player One", age = 65, health = 20, damage = 2} -- *Main> enemyOne -- Person {name = "Enemy", age = 2, health = 5, damage = 2} -- *Main> attack playerOne enemyOne -- Person {name = "Enemy", age = 2, health = 3, damage = 2} -- *Main>
Hououin Kyouma · 2019-04-25 02:19
>>1910 Personally, I think people should be really careful with laziness in Haskell especially when doing IO. >>1931 Haskell isn't slow, Laziness is; The mere fact that the RTS has to create a thunk for every loop that happens within the Haskell Program introduces overhead but if one knows how to optimize a Haskell Program (e.g. knowing when to use unboxed types and identifying which functions are strict and lazy and correcting them if needed) then Haskell would be on par with C or even better. Channable was able to create a search algorithm for indexing in Haskell much faster than the current implementations available.
Marly Krushkhova · 2019-07-22 10:20
God I love this language but the creator of Shen is right when he says programming in haskell is like only having protected sex all the time with your wife. I might just become evil and start using template haskell everywhere.
Spooky · 2019-07-22 16:41
>>13363 Isn't laziness faster because if it doesn't need to evaluate something it doesnt X=10 If X == true or x < 10 The first condition is met so it doesn't test the second
BloodCat · 2019-07-22 22:07
>>14335 >The first condition is met so it doesn't test the second I think most c-style languages do this too.
Chani · 2019-08-28 10:46
I wanna make a really simple web api to hook up to a database to use for some projects, any reccomendations for things to read?
Vasya Pupkin · 2019-08-28 10:53
>>14338 Any language with side effects has to do this.
Hacker · 2019-09-26 14:54
Can someone explain what's the point of functors, applicative functors and monads in Haskell for a guy who was programming in C and Java for most of his life?
Bobby Newmark · 2019-09-26 17:29
>>1012 Could you give an example of what you have done with Haskell or are planning to do with it? I haven't yet got the slightest idea and am interested.
John Doe · 2019-10-08 17:27
>>15398 >mfw killed the thread with too painful question
Yet Another Lainon · 2019-10-13 11:44
>>1012 Any tips to set up a usable and discoverable Haskell environment (preferably in Emacs) without all that HIE and LSP nonsense? A few years ago it was possible to compile a single binary for completion, and that was good, but since then it dosn't compile anymore.
Morpheus · 2019-12-16 02:16
>>15522 I 've done a game, and i 'm doing an audio app and a game now.
Pris · 2020-01-11 02:09
>>16234 what kind of game was it?
Switch · 2020-01-27 06:30
>>1630 A Monad class defined in terms of join interacts badly with -XGeneralizedNewtypeDeriving: https://gitlab.haskell.org/ghc/ghc/issues/9123
Mitnick · 2020-01-27 06:34
>>15396 Same as any other abstraction you introduce into a language. It enables code reuse. If you have ever written code like: if (x != NULL) { if (y != NULL) { f(x, y); } } Or: for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { f(i, j); } } The Applicative typeclass gives you the tool to abstract over both of these patterns (and many others similar ones).
Leto Atreides I · 2020-03-30 05:22
I wanted to fuarrrk around with SDL in haskell, but I can't seem to manage even a simple test program: module Main where import SDL import Linear import Control.Monad import qualified Data.Text as T main :: IO () main = do initializeAll window <- createWindow (T.pack "asdf") defaultWindow renderer <- createRenderer window (-1) defaultRenderer gameLoop renderer gameLoop :: Renderer -> IO () gameLoop renderer = do events <- pollEvents rendererDrawColor renderer $= V4 0 0 255 255 clear renderer present renderer let shouldQuit = elem QuitEvent [ eventPayload ev | ev <- events] unless shouldQuit (gameLoop renderer) Compiling works fine under stack, but trying to actually run the program consistently ends in a segfault. Is my code fuarrrked or is something else wrong? **I didn't even know Haskell could segfault** >>15396 They're useful for enabling side effects in an otherwise purely functional language and also for generic functions, e.g. fmap.
Dr. X · 2020-05-04 03:29
I'm hoping a haskellian or similar person can assist me with something. I'm trying to understand monads in theory, and it seems basically like a special type that encodes state into its subtypes. (I know enough Rust to use its syntax, and I generally understand the format of Haskell's) Is that correct? Is this similar to the idea of a higher-order function that calls different functions for various states? Think of each function call as a continuation, and which continuation is picked is based on the impure feature being wrapped. So the higher-order function would close over something mutable, and the state of that internal mutable entity determines the function called.
Lady 3Jane.. · 2020-05-04 12:21
>>18247 That sounds on the right track to me. A monad is a way to carry around some extra information (e.g. state, configuration, logs, failure, multiple results) during a computation without explicitly specifying how to deal with it at every step. It relies on defining a bind operation so that the program knows how to combine this extra information. So with state it knows it has to sequentially pass the state to each function as it is mutated, with failure that it should propagate (short-circuit) the failure through the rest of the computation, with multiple results to run later functions on each possibility and combine them, etc. I am not sure about their link to continuations. I vaguely remember them being partway to a continuation, but requiring an extra definition.
The Phantom Phreak · 2020-05-04 14:27
>>18259 This is very helpful, thanks for lending your expertise. I would appreciate anybody else chiming in about the second part in particular. I'll still keep researching it, pretty neat stuff.
Unnamed · 2020-05-05 23:40
>Most types in GHC are boxed, which means that values of that type are represented by a pointer to a heap object. The representation of a Haskell Int, for example, is a two-word heap object. An unboxed type, however, is represented by the value itself, no pointers or heap allocation are involved. >Unboxed types correspond to the “raw machine” types you would use in C: Int# (long int), Double# (double), Addr# (void *), etc. The primitive operations (PrimOps) on these types are what you might expect; e.g., (+#) is addition on Int#s, and is the machine-addition that we all know and love—usually one instruction. >Primitive (unboxed) types cannot be defined in Haskell, and are therefore built into the language and compiler. Primitive types are always unlifted; that is, a value of a primitive type cannot be bottom. We use the convention (but it is only a convention) that primitive types, values, and operations have a # suffix (see Section 7.3.2, “The magic hash”). For some primitive types we have special syntax for literals, also described in the same section. So basically, it is impossible to take advantage of cache. Even if you use the nice vector library, it's a vector of pointers to structures of pointers to raw data types. Constant cache pollution. Yes, plenty of other languages have the same problem-- Java, Python, etc. But it's still a major downside worse than GC in many ways. I love Haskell, but whenever I want to make a program that truly runs fast but also has nice types, I guess Rust is the main option.
Neo · 2020-05-06 07:52
>>18295 vector comes with unboxed vectors. is that not what you're after?
Yamaoto Toshi · 2020-05-07 09:52
>>5086 This is an old post, but I'd answer it, in case if someone ever wanted another feedback about this book from a Haskell beginner. I think it's a mixed bag in how things are explained and you definitely need external resources to grasp some of the concepts and practical uses of some construct. It also lacks practical examples. I still think it's a good starting point, no bullshit introduction to the language presenting just enough information to get into "real" functional programming. If your goal is to have a solid theoretical foundation for FP this will definitely be too light, otherwise it's worth to get through if new to Haskell. The free online version is even better than the paper one. Hlint and a syntax checker (like flycheck in Emacs) are also very valuable to understand the type system better and write more "idiomatic" code
hash table · 2020-05-07 10:52
why de fuarrrk there are 2 haskell threads?
Hitomi · 2020-05-07 14:53
>>18325 i like learn you a haskell for great good because it has cute pictures.
Spike Spiegel · 2020-05-07 20:51
>>18306 Unboxed vectors of unboxed types, no? IE, you can't have an unboxed vector of custom data types.
William Holtzer · 2020-05-08 20:04
I really like haskell for small challenges but I haven't used it for any real projects. Does anyone have reccomendations for beginner projects to write in haskell?
Ein · 2020-05-09 07:12
>>18330 not automatically no, but you can make your custom data type unboxed if need be... i usually default to boxed vectors, then if i need to speed it up i run the profiler and replace any bottlenecks with unboxed or small mutable loops.
Dox · 2020-05-09 07:14
>>18355 https://en.m.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours
Batou · 2020-05-10 08:12
>>18355 >I really like haskell for small challenges Same for me, I grind Exercism since the last few days and I'm really enjoying how readable and expressive it is, on top of fitting the bill for everything I wanted in a new language so far. I already tried and failed to learn Ocaml many years ago but since then I always had pattern matching, type declaration and "let" bindings in the back of my mind, so it feels really good to finally master the basics of a language where those features strongly integrated
Nell · 2020-05-13 14:10
>>18361 Bad use of cache is not really something that shows up in a profiler because it is a pervasive problem.
overriding · 2020-05-13 14:56
>>1012 Noob to Haskell here. Can someone tell me what's so good about Haskell? Often times I've seen other people call it a 'meme' programming language. What's are it's strengths and it's flaws? What are its use cases in general other than hobby programming? How does it compare to other functional languages? Do note that I only know some basic LISP programming.
Jet Black · 2020-05-15 14:10
>>18501 I'm not a haskell user but do notice that if you actually listen to (and base your actions on) one who calls sothing a "meme'" then you're doing it completely wrong. (everything is a meme, anyways). To answer your question, all I know is that it is a perfectly usable language, as good as any other, and the formalism on which it is built is solid and really amenable to formal verification. Now if you're (as you seem) only interested in the industry-side of programming, it is likely you would rather go to the usual suspects: java, php, C++, js, python.... On the other hand you seem interested in something different, thereupon lies I believe the axis of your choice wether to check it out or not. You're also wasting time waiting for an answer in a meme imageboard instead of just looking up some resource on how haskell does the art of programming. Pic related may be an interesting read on that matter.
Moore · 2020-05-15 14:14
>>18551 >if you actually listen to (and base your actions on) one who calls sothing a "meme'" then you're doing it completely wrong. (everything is a meme, anyways).
Hagbard Celine · 2020-05-15 15:01
>>18501 It is fun. I tried to learn other programming languages before it, but gave up after a while since they all felt tedious and I couldn't imagine myself writing anything complicated in them. With haskell it takes a while to understand how to do something, but once you have it you have something "solid" that you can generalise and compose with other code easily.
Wirth · 2020-05-15 15:41
>>18500 But the profiler will tell you which part of the code is sucking up the most time, then you go there and unbox that part.
Pris · 2020-05-15 18:14
How do you set up your IDE? I've been using nvim and ghcid plugin, but it is just terrible. haskell.vim provides broken syntax highlighting, hasktags do not really work with modules, and I'm sick of using grep to find a function definition or call sites. Terminal mode breaks when with ghcid plugin on you want to open another ghci session inside of vim. stylish-haskell sometimes deletes my comments and I'm yet to integrate hlint inside of vim somehow, now I just generate an html page with all warnings and scroll through it.
Unnamed · 2020-05-15 18:38
Just curious, what is the color scheme of the code samples here?
Boole · 2020-05-17 05:19
>>18554 This idea that your program is optimized if you optimize a few hot loops is delusional. Performance means all your code needs to be fast, not just little parts of it.
Hitomi · 2020-05-17 11:41
>>18584 lol
Stallman · 2020-05-17 17:42
>>18558 Looks like Gruvbox
Ein · 2020-05-18 03:47
>>18593 >write program in Ruby >optimize hot loops >look ma, it's performant now!
The Phantom Phreak · 2020-05-18 07:35
>>18611 you just described all numerical analysis in python, so it is apparently good enough for a large chunk of industry and academia. bindings to fast linear algebra libraries, with the less time sensitive steps in native python. sure you can go faster and write everything in C, but why waste hours of your time to shave a few ms off of the remainder of the program?
Koichiro · 2020-05-18 15:30
>>18616 You are talking about programs that spend the vast majority of their time in C/C++ code. That C/C++ code does not just optimize "hot loops," every part of it is optimized. The entire function/program is one giant hot loop. It is a plain fact that code not taking advantage of cache is performing at a tenth or even a hundredth of what it could be. And this is a huge amount of the code we run today. It all adds up to a steep cost. Haskell incurs the cost. I'm not saying it's never usable, but just that we should not twist ourselves into knots trying to justify this cost for programs that persist. Programs that persist and do substantial computation should not be slow. Profilers do not show you when your entire program is stuck in a swamp of molasses, they only show you which parts of the swamp are relatively worse. You simply will not get perf unless you take advantage of hardware. These days you don't have to write C to do it. Rust is an option and it's very pleasant to use. Hence what I originally said-- Haskell is nice, but when I want a personal project to run fast, it's not an option and I'll use Rust. Aside from that, a huge part of academia and industry are awful. We are talking about people who think Node.js is ok. It's not.
sage · 2020-05-20 06:58
>>18624 >That C/C++ code does not just optimize "hot loops >The entire function/program is one giant hot loop These are contradictory, evidently. Frequently, the latter is true and the former thus false. >code not taking advantage of cache is performing at a tenth or even a hundredth of what it could be. Whereas this depends on the computation, i'd be interested in a concrete statement on the matter if you have a reference. Your comparison of numpy to node.js is offensive. numpy is beautiful marriage of expression and efficiency.
FILLER · 2020-08-25 02:11
>>13205 It's good but have fun getting the library to work
Yamaoto Toshi · 2020-09-04 21:25
Been trying to learn Beam currently, its a real pain how little the Migration library has been documented, and even just things like "heres how to connect to a postgres db easily" but Im gonna stick with it. Figure with that and Servant I can create apis for Elm sites and get into freelancing soykafty modern websites blurgh Side note, but does anyone have a pdf of this? https://leanpub.com/functional-design-and-architecture it looks really interesting but I can't afford it since I lost my job
byte · 2020-09-04 21:52
What about category theory? Looks just like mathematicians playing around with programming. LOL
Agent Smith · 2020-11-01 11:05
>>1466 >since you can always write the same in C. This is wrong
John Titor · 2020-11-01 13:25
>>21748 Can you explain this? I would assume that all Haskell code can be transpiled to C.
Cutter · 2020-11-01 22:45
>>20454 it's too good but takes a day to get working with HLS
Boole · 2020-11-02 03:29
>>21749 All languages are Turing-complete, but some are more Turing-complete than others.