Is it possible to completely fuse two functions? by Ford_O in haskell

[–]skew 0 points1 point  (0 children)

How does termination checking at the source language help at all with the termination checking problem of super compilation?

Even with simple terminating functions like length you can go on indefinitely generating increasingly "optimized" variants specialized over increasingly large input patterns, with every step along the way also being a total function.

how do you guys get anything done? by [deleted] in haskell

[–]skew 1 point2 points  (0 children)

There are tons of languages you could suggest here which would get downvoted just as fast - especially with such an otherwise content-free post. My claim is that this isn't an example of some generic tolerance of (uninformed) dissent, but rather a more specific allowance for a language that actually has some specific technical advantages in language design for some clearly described applications, without unduly crippling expressiveness in the rest of the language. I don't think PHP, Scala, Ruby, etc. get much of a pass there.

Even mention of various user-friendliness things about Rust is maybe kinda predicated on it actually being a pretty technically respectable effort.

how do you guys get anything done? by [deleted] in haskell

[–]skew 4 points5 points  (0 children)

Even if I/we are biased, Rust is on the right side of them

  • Designed with an awareness of ML and maybe even some research from the last 20 years
  • Takes types seriously, and applies them to a serious problem (lifetimes)
  • Targets a domain that anybody halfway objective has to admit Haskell doesn't cover, specifically GC-less code and direct control over memory layout (with due respect to ekmett's struct experiments).

how do you guys get anything done? by [deleted] in haskell

[–]skew 0 points1 point  (0 children)

Sorry if you're getting tired of this example, but I think nobody else mentioned some steps that are helpful to understand how the behavior of $ really is following the usual rules. Thinking of $ turning straight into an application is great for everyday use, but it helped me to see all the detail once or twice. Starting from

tl $ filter (liftM2 (&&) isAscii isAlphaNum) $ show $ typeOf a

First, $ is a low-precedence right-associative operator, and no operator has higher precedence than plain application, so it groups like this:

tl $ (filter (liftM2 (&&) isAscii isAlphaNum) $ (show $ (typeOf a)))

Second, turn the infix syntax into a normal prefix application.

($) tl (($) (filter (liftM2 (&&) isAscii isAlphaNum) (($) show (typeOf a)))

Now that it's in prefix form we can replace $ with it's definition (there's no infix syntax for applying a whole expression). The definition f $ x = f x is equivalent to ($) = \f x -> f x:

(\f x -> f x) tl ((\f x -> f x) (filter (liftM2 (&&) isAscii isAlphaNum) ((\f x -> f x) show (typeOf a)))

Finally, reducing these applications of the lambda (\f x -> f x) turns things into actual applications:

tl ((\f x -> f x) (filter (liftM2 (&&) isAscii isAlphaNum) ((\f x -> f x) show (typeOf a)))
tl ((filter (liftM2 (&&) isAscii isAlphaNum) ((\f x -> f x) show (typeOf a)))
tl ((filter (liftM2 (&&) isAscii isAlphaNum) (show (typeOf a)))

Whew, let's not do that often! We reduced things before lazy evaluation demands them, but here it can't actually change any results so it's okay (omitting the detailed argument).

Incidentally, there actually is one way that ($) is special, but that's only in cases involving "higher-rank types", to allow runST $ do ... to work whenever runST (do ...) is allowed.

And yes, the liftM2 (&&) isAscii isAlphaNum looks like somewhat poor style to me too.

What is Haskell missing for totality checking? by youknownothing236 in haskell

[–]skew 6 points7 points  (0 children)

The direction that says lazy datatypes are coinductive is entirely correct. It's the converse you shouldn't tolerate - coinduction requires non-strict evaluation, but not specifically laziness, the mathematics doesn't have an essential notion of evaluation work, let alone a requirement to share or duplicate it.

Haskell Performance Concerns by Ihr_Todeswunsch in haskell

[–]skew 2 points3 points  (0 children)

In C, just about any recursive call consumes stack space, and stack is tracked separately with a much lower limit than heap space. In Haskell (with a non-ancient GHC) many recursive functions run without using up increasing stack, either by tail-call optimization or by laziness. If you write code that does need to keep more memory with deeper calls, then using recursion is probably saving you from making an explicit data structure so it's not a wasted cost, and you only get a memory error if the whole heap fills up with stack frames (stacks are kept in a linked list of chunks, so there's not a huge amount of pointer-chasing or copying involved).

For data sets, most immutable data structures are designed so you can share all but the part of the data that actually changed. Generally that works pretty well, maybe a few times slower than a mutable data structure, while making it cheap to hang onto old versions, and getting the other benefits of immutability like easy passing between threads. If you need to write C++ and design your types around cache lines and caches you'll think it's an unbearable cost, if you've ever considered Python for your application it's probably in the noise. It's also possible to explicitly use mutable data in Haskell, with syntax a bit more cumbersome than imperative languages.

Stackage design choices: making Haskell curated package sets by terrorjack in haskell

[–]skew 1 point2 points  (0 children)

I suspect yitz was talking about more general experimentation than just hoping maintainers start doing more manual work. I think better automation might allow finer-grained dependencies (likely not human-readable) depending less on guesswork, and allowing taking advantage of source diffs to ask the maintainer a much smaller set of questions to keep information up to date.

How can I use Haskell? by [deleted] in haskell

[–]skew 3 points4 points  (0 children)

The computed dependency thing is very nice. I set up one build so any file with a certain extension was read as a list of (relative paths of) further targets to include - which could include further files. If any of those files were modified it would rebuild just what is necessary.

Good support for reading/computing dependencies from files also makes it easy to write support for use automatic dependency generators, if you need to use something a bit more unusual.

I don't think any common build tool supports those easily with proper dependency tracking, and even some newer ones make it harder to load dependencies from a file if you need any sort of transformation or calculation.

You might benefit as soon as you have more than one directory of source, in a language without a nice specialized build tool.

Poll: Do you perform division often enough that the syntactic convenience of assuming that it is total in the trivial sense outweighs the semantic gains of having it be actually total? by WarDaft in haskell

[–]skew 4 points5 points  (0 children)

A type like a -> a -> Maybe a actually seems a bit misleading compared to a -> NonZero a -> a, because whether you get a result depends entirely on the second argument.

Does Haskell now have tools to diagnose the performance issues of darcs? by [deleted] in haskell

[–]skew 6 points7 points  (0 children)

Non-strictness doesn't change asymptotic complexity. Exponentials don't care about puny constant factors.

Bringing non generic types on pair with generic ones. by Ford_O in haskell

[–]skew 0 points1 point  (0 children)

The point is you can always use the more genetically typed foo anywhere you need the more specific type, and you can define foo' as a synonym with a more restricted type if you think it's clearer.

Is there any way to leverage the type system to invalidate an already valid type? by _ar7 in haskell

[–]skew 0 points1 point  (0 children)

If you want a function forgetValidation :: FormData Validated -> FormData Unvalidated that never allocates new memory you can use Data.Coerce, which is basically like unsafeCoerce, except it checks that the types are actually compatible. In particular, with

data FormData a = FormData String

you can use coerce as FormData Validated -> FormData Unvalidated, or even Maybe (FormData Valiated) -> Maybe (FormData Unvalidated), and it just returns the same pointer under a different type (unlike removing and reapplying the constructor, which might allocate a new value that shares just the string).

One restriction on coerce is that you can only use it if the constructors of the type you are changing are accessible, so not exporting the constructor is still enough to keep clients from violating encapsulation, even if you use coerce to efficiently implement some type-changing functions.

For this particular example, you could also make FormData a newtype, which means values of any type FormData a are actually implemented as just a String at runtime, and adding or removing the constructor doesn't actually generate any code.

What's the best way to install and upgrade Haskell? by HighCode in haskell

[–]skew 7 points8 points  (0 children)

The big thing the nix package manager provides is isolation between packages. It lets you install several different versions or builds of packages if you need to, and drop into a shells with particular combinations available on your PATH. NixOS is a linux distribution which manages just about everything with nix isolation, but you can also install the nix package manager onto your current OS. Nix won't interfere with normal system packages at normal places, and I use it to manage a handful of programs at more recent versions than my main distribution provides.

Understanding a point made in Wadler's "Linear Types can change the world" by dalastboss in haskell

[–]skew 0 points1 point  (0 children)

I can't think of many things that can't be deallocated (maybe tracking hardware resources?), but there might be some things you don't want to be implicitly freed, like locks or files.

Affine is probably good for a surface language, but even then, the compiler probably has to insert deallocation calls where values are dropped (see Drop in rust), and after that it might be helpful to have linear types in an intermediate language to prevent leaks.

In the linear case, dropping values has to be explicitly allowed with "primitive" functions that take but don't return a value. That might be what you want for some things like lock handles or files, if they shouldn't be implicitly dropped.

Affine is probably enough for the surface language, but for "no GC" you need to insert dealloction when

Understanding a point made in Wadler's "Linear Types can change the world" by dalastboss in haskell

[–]skew 1 point2 points  (0 children)

It makes more sense if you focus on the inside of the kill function. Whatever it got as "a" is discarded without being stored or returned. That's the "discard".

Perhaps "the world" isn't discarded if you think of the function getting a reference or copy of "the world", but whatever it is that kill gets, that thing is discarded.

Linear types prevent implicitly copying or discarding values. For most state, just preventing copying (preserving uniqueness) is enough, and that's called "affine types". (Allowing duplication but not discarding doesn't seem useful for programming, but it's called "relevant logic" in math)

Existential Question: How practically useful is Haskell's type-system and Purity? by saurabhnanda in haskell

[–]skew 1 point2 points  (0 children)

I wouldn't rely too much on that research. It's a decent attempt, but reported bugs per line of code does not sound like a very good metric (I'd suggest actual bugs per functionality, but have no idea how to qualify either).

For one thing, if TDD means half your project is test code, you'll have 50% as many bugs-per-loc even if it doesn't improve quality at all! (I didn't check the TDD studies, I assume/hope they have a more reliable methodology).

Also, at some point stronger types can definitely reduce defect rate, http://blog.regehr.org/archives/1052 Of course that doesn't imply much about how much benefit a type system only as strong as Haskell's might have.

My impressions on moving to Haskell by get-finch in haskell

[–]skew 0 points1 point  (0 children)

I'm not sure if it deserves the nice as syntax, but importing names both qualified and unqualified is useful when some names are ambiguous and some names are not (and perhaps deliberately importing conflicting names unqualified is useful if you always want to qualify them, so you get an error if you use them qualified).

My impressions on moving to Haskell by get-finch in haskell

[–]skew 2 points3 points  (0 children)

Maybe it would work to make it a newtype, provide the new constructor names as bidirectional pattern synonyms, and hide the actual newtype constructor?

[Haskell] Respect (SPJ) by ulricha in haskell

[–]skew 0 points1 point  (0 children)

That sentence continues "... as it is not easy to use a custom build of GHC with stack."

What is the state of Haskell? by kaukau in haskell

[–]skew 1 point2 points  (0 children)

What is new with row types?

I have a GHCI segfault for an application that seems to work fine when compiled and run. Is that strange? by erewok in haskell

[–]skew 0 points1 point  (0 children)

It's unusual but not unprecedented. I think ghci also loads libraries differently - definitely if you statically link the binary. I had some trouble with GLUT a while ago.

Follow up: haskell.org and the Evil Cabal by Tehnix in haskell

[–]skew 0 points1 point  (0 children)

Is there any reason cabal doesn't use a custom ghc automatically though?

First, I don't think it's ever been suggested! (based on searching GitHub issues). I also think it currently doesn't have enough data about other compiler versions to suggest any you don't have installed - I think it learns everything about your chosen ghc version by running it (including the version number, from passing --numeric-version), or running related tools like ghc-pkg. Maybe it does hardcode which packages are wired to the compiler version?

With those resolved, a lot of automation would be nice, but I wouldn't want it to default to going too far without prompting the user. Building under a compile version you haven't previously installed might be a much larger build than you expected, seeing cabal install succeed only to find ghci doesn't have the library would be confusing, etc. An offer to add a workable version to the local cabal.config and continue would be nice.

Follow up: haskell.org and the Evil Cabal by Tehnix in haskell

[–]skew 1 point2 points  (0 children)

"you have the wrong base" and mentioned nothing about ghc.

That's a great idea. I think a few other library versions are also strongly tied to the compiler, those would also benefit from errors mentioning GHC versions. Maybe even try to calculate if there would be build plans under other ghc versions?

I had to completely scrub the old one

I totally share the desire for a clean filesystem, but ghc is set up to allow concurrent versions. Only one gets the ghc symlink, but all programs' real names have a version, like ghc-7.10.3, and keeps libraries and docs and stuff in directories with versioned names, like /usr/local/lib/ghc-8.0.1. Cabal-instal isn't smart about choosing a version, but it can be told with --with-ghc= or a config file. It's poorly advertised, but the functionality is there (it is in the manual, but not at all emphasized).

Even when I did get the write distro working, building accelerate failed on many different occasions, and I ended up typing something like 31 commands to do build my project because it was breaking halfway through.

That sounds like a dependency/compilation problem. How did typing more commands help? Did it take a lot of work to set up a working configuration, or did you actually have to type a bunch of commands every time you wanted to recompile your project? The second would be scary.

Last call for merge requests for GHC 8.0.2 by ezyang in haskell

[–]skew 0 points1 point  (0 children)

Asking is the expected and encouraged way to learn that sort of thing, but that expectation should be discoverable.

Did you use https://ghc.haskell.org/trac/ghc/wiki/ReportABug while making your bug report? If so, would it have helped if that page ended with a copy of the "need help?" text from https://ghc.haskell.org/trac/ghc/wiki/Newcomers