HNHacker News
TopNewBestAskShowJobs

chas

447 karma · joined November 20, 2011

computing, machinery

[ my public key: https://keybase.io/chas; my proof: https://keybase.io/chas/sigs/3e4ZitlD0tm8a9ZVzI7rkK5G03snHd2qvx2ABwqOtHI ]

submissionscomments
chas··on Formatting floating point numbers
Or you aren’t doing something physical. For example there are tons of things in math that can use as much precision as you want. For a toy example, looking at rates of convergence or divergence in extremely small regions of the Mandelbrot set. There are techniques that cut down the requirement for precision for that problem, but they are necessary because the default level of precision is insufficient.
chas··on Why GitHub used Haskell for Semantic
I think it's important to be precise about how the monad abstraction and type system features interact in order to combine pure and impure code. I wrote a comment elsewhere in the thread (https://news.ycombinator.com/item?id=20112333) where I conclude that while the monad abstraction is useful for making a usable interface and writing programs which are agnostic to how their state is implemented, the fundamental work of distinguishing pure and impure computations is accomplished with a combination of type system features and compiler magic.

The case is exactly the same for the Clean language as for Haskell and indeed Clean has Monad instances for all of the types I mentioned aside from STM, so there are no concerns with dealing with those monadic abstractions in Clean. (https://imgur.com/a/sjsDiZq, https://cloogle.org/#using%20Monad) Since IO is Haskell's type that marks impure computations, we can compare Haskell's implementation to the equivalent one in Clean (interface: https://cloogle.org/src/#Platform/System/IO;line=10, implementation: https://cloogle.org/src/#Platform/System/IO;icl)

In Clean, IO is implemented as follows:

    :: IO a = IO .(*World -> *(a, !*World))
In Haskell, it is:

    newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
(for full context see: http://hackage.haskell.org/package/ghc-prim-0.5.3/docs/src/G..., the related monad instance is here: http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GH...)

These both implement IO as a function which takes the state of the world as its input and returns a new state of the world as it's output. This is encoded using the state transformation that I mention in the other post (https://acm.wustl.edu/functional/state-monad.php) Both implementations also go on to define Monad instances for their new IO type. The major difference is that the Haskell standard library only exposes bindIO and returnIO to the user and hides the internals of IO from the user and Clean allows the implementation to be a normal library.

That difference is Clean's uniqueness types showing their strength. Clean can explicitly expose it's predefined World type (https://cloogle.org/doc/#CleanRep.2.2_6.htm;jump=_Toc3117980...) to the user with the guarantee that you can't write a function of type IO a -> a because it would violate the uniqueness properties and thus be a compilation error. Haskell instead uses the module system to keep State# RealWorld from being exposed to the user. This means that if you as a user want a different set of abstractions for impurity in Clean, you can build from the World level rather than needing to construct it out of what can be done with bindIO and returnIO. For details on what's going on with State# see https://www.fpcomplete.com/blog/2015/02/primitive-haskell

From the perspective of "the value prop for learning/using monads", this discussion leaves us in a worse place than where we started because the conclusion is that uniqueness types aren't a get out of monads free card and that Clean uses the many of the same Monad-related abstractions as Haskell does and uses them for the same purposes. In order to not leave you out in the cold as to the value prop for the monad abstraction, you can see how it works for a number of different Monad instances in Tikhon's answer on Quora (https://www.quora.com/What-are-monads-in-functional-programm...), though he chooses to use join, fmap, and return as the fundamental parts of a Monad, rather than bind and return, as I have here. As he touches on in his discussion, it's common and straightforward to implement one definition in terms of the other, so anything you learn from about that definition can be ported the definition I use without much fuss, so don't worry if it doesn't match at first. What this means is that if you have a tools in the standard library that only depend on features of Monad, you can use the same small collection of functions to solve a ton of problems.

chas··on Why GitHub used Haskell for Semantic
Note: The approach of structuring the interactions with the IO type with the functions (bindIO :: IO a -> (a -> IO b) -> IO b) and (returnIO :: a -> IO a) is still using the abstract idea of monads to organize the impure code and make it ergonomic to work with, so "monadic I/O" or "monadic state" aren't entirely misnomers. The thing I wanted to emphasize is that you don't need to know the word "monad" or understand anything in particular about the design process for the Monad typeclass in order to use these libraries.

I think focusing on the "monad" part over the "IO" part of "monadic IO" is particularly confusing to new users because the abstract idea of a monad is very general, so if you assume all places where it shows up are basically like the case of IO, you will be very confused. Further, it makes the idea of a monad seem like a Haskell-specific hack, rather than a general abstraction that can be used in any programming language you want to.

This is particularly important to emphasize because the abstract idea of monads only makes the IO approach to impurity nice to use, it doesn't make it possible. Haskell had I/O (and other impure capabilities) before the monadic way of organizing impure code was introduced. The heavy lifting for IO is done by having a type system strong enough to prevent a function of type IO a -> a from being written by an end-user. If you have written a monad abstraction in a language without such a type system[0], it can still be a nice abstraction, but it doesn't guarantee that pure and impure computations can be distinguished on the type level.

[0] https://www.nurkiewicz.com/2016/06/functor-and-monad-example...

chas··on Why GitHub used Haskell for Semantic
Sorry for the additional pedantry, but I think this important to be precise about given the target audience of your comment.

Monads aren't the separation between purely functional and stateful code. The Haskell type system maintains that separation. Anything that's doesn't return IO a for some a appears to be a pure function from the perspective of the programmer. Once a function returns IO a, there aren't any* functions provided by the compiler that can make a function that uses those results not also return IO b for some b. For example, the type of getLine is IO String (because it impurely produces a String) and the type of putStr is String -> IO () (because it takes a String and mutates the world without returning anything).

If the compiler provided a function for computing on the a in the IO a, for instance, bindIO :: IO a -> (a -> IO b) -> IO b and a function to wrap the results of non-IO functions, such as returnIO :: a -> IO a, you could do arbitrary computation with these IO-wrapped data types, but know at a glance if your functions were impure.

This approach doesn't require the Monad typeclass at all, just a magic type called IO that tags impure computations that are implemented with compiler and runtime magic. It happens to be the case that this is exactly how GHC implements the IO type. bindIO is implemented here[0] and returnIO is implemented here[1] and the compiler magic used to implement them isn't* exported, so all IO operations have to go through those functions. It is not a coincidence to that these functions have the right types to form a Monad instance for IO and indeed, that is also present[2], but the IO type and the type system that ensures it can't be sneakily hidden are doing the heavy lifting, and the Monad instance (and accompanying syntactic sugar), are just there to make it nicer to work with and easier to abstract over.

If you have a passing familiarity with Haskell, the phrase "state monad" is the obvious place where my claims stop making sense. In fact, the State type only supports computations that are entirely pure. If you want to simulate global variables in a language that didn't have them, you could always pass all of your global variables to every function and get updated ones back from the function along with the nominal results of the computation. The State type is just a regular data type that wraps stateful functions constructed by such state passing. A type of the form State Int String is just a function that takes an Int and returns and String and an Int, no compiler or runtime magic needed.

You can play the same trick as in the IO case and provide functions bindState :: State s a -> (a -> State s b) -> State s b and returnState :: a -> State s a in order to compute on these "stateful" values while making sure the result state got passed to the next function in the chain correctly. Like IO these two functions can be used to create a Monad instance for State. Unlike IO, State is just a data type holding a regular Haskell function, so it's extremely reasonable to write a function of type State s a -> s -> a which runs the State s a computation with an initial value of type s. This is written by unwrapping the State type and then passing the initial state value to the function inside and return the result while ignoring the returned new state. More details on how State is implemented are available here[3].

A complication to this is that if you want stateful mutation for performance reasons, the ST type[4] also exists, which looks identical to the State type from the programmer's perspective, but plays similar tricks to IO in order to actually mutate under the hood while not exposing the implementation details to the user, so it can be reasoned about exactly as if it was pure and using the same implementation as State.

These Monad instances for IO, State, and ST start to pull their weight when you write functions that only use features provided by the Monad typeclass and they work seamlessly with any implementation of stateful computation despite their very different internals. Monad is quite general, so if all you care about is abstracting over stateful computations, you can also use the methods from MonadState[5] which allow you to interact with the state along with the results of the computation independent of the implementation of stateful computation.

* In the name of not getting bogged down in details, there are a few parts of this discussion that are not entirely accurate, particularly around functions like unsafePerformIO[6].

[0] http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GH...

[1] http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GH...

[2] http://hackage.haskell.org/package/base-4.12.0.0/docs/src/GH...

[3] https://acm.wustl.edu/functional/state-monad.php

[4] http://hackage.haskell.org/package/base-4.12.0.0/docs/Contro...

[5] http://hackage.haskell.org/package/mtl-2.2.2/docs/Control-Mo...

[6] http://hackage.haskell.org/package/base-4.12.0.0/docs/System...

chas··on Why GitHub used Haskell for Semantic
If you want to be productive in Haskell, the Monad typeclass is an important tool to familiarize yourself with. That said, unless you are working on the internals of a few libraries, you don't really ever need to know serious category theory in order to be very productive. If you don't already have a background in abstract algebra or category theory, I think a better approach to learning these abstractions is slowly work through the typeclassopedia[0] while solving problems the naive or clunky way and then start to use the fancy-name abstractions (e.g. Functor, Applicative) as you see how they could be useful.

On that front, the Monad typeclass is far more general and useful than just for IO and State, so if you are thinking of it as primarily a hack to deal with those, you probably won't get the hype. In addition, it's really useful to work with a large number of examples of different Monad instances (IO, State, Maybe, List, STM[1] if want to get a bit further into the deep end) instead of just staring at the methods in the typeclass and hoping it make sense. It's a pretty broad abstraction, so it will only make sense if you are familiar with what it's abstracting.

[0] https://wiki.haskell.org/Typeclassopedia

[1] http://book.realworldhaskell.org/read/software-transactional...

chas··on Why GitHub used Haskell for Semantic
I wrote a something[0] that demonstrates Haskell programs side-by-side with a Java program for a super toy problem. It goes on to explore more complex Haskell abstractions which implement the same simple program using less approachable techniques.

It is primarily meant for helping people understand how the abstractions work, rather than make an argument for when they are good to use, but it might give you enough background to understand the discussion around Haskell abstractions.

[0] http://reduction.io/essays/rosetta-haskell.html

chas··on Nvidia to Acquire Mellanox for $6.9B
If you want to run a computation on more than one of those AI (and scientific linear algebra) chips, you need some network to connect them. The higher the bandwidth and the lower the latency of that network, the less likely the network performance limits total system performance. See NVLink as an example of Nvidia’s related work. (https://en.m.wikipedia.org/wiki/NVLink)
chas··on AI and Compute
Similar to how linear transforms can be represented as 2-dimensional arrays of numbers (that is to say matrices)[0], tensors are a higher dimensional analogue with a rich theory in their own right and a representation as higher-dimensional arrays of numbers. Similarly, if you look at a tensor solely as an n-dimensional array of numbers, it ignores important differences in the mathematical behavior of objects with the same representation. To give an example: Different parts of a tensor can behave differently under change of basis. [1]

[0] https://www.youtube.com/watch?v=kYB8IZa5AuE

[1] https://en.wikipedia.org/wiki/Covariance_and_contravariance_...

chas··on AI and Compute
That doesn’t really apply in this case though because the major thing people are using the increase in parallelism for is running larger computations or more parallel computations of the same size, rather than trying to run the same computation in less time.
chas··on Programming Language Theory in Agda
I think Practical Foundations for Programming Languages [0] does a good job on that front.

[0] https://www.cs.cmu.edu/~rwh/pfpl/2nded.pdf

chas··on Ask HN: Is machine learning worth learning for hobbyists/pet projects?
Machine learning is a bigger set of techniques than deep learning. Linear regression and random forests still work fine and can get good results in many problem domains without particularly much compute hardware. In addition non-learned feature engineering can get good results in computer vision if you constrain your input images.

Do you have particular application areas or problems you want to apply ML to?

chas··on TSMC Kicks Off Volume Production of 7nm Chips
It makes it so all of the chips they will use have all of their neighbors, so the process (and thus electrical properties) will be more uniform between chips near the edge and chips near the center.
chas··on Coinbase Ventures
I don't think that aspect of centralized banking infrastructure has "very good UX" either. I could imagine something like PGP where the key management around hardware wallets and an interface like https://etherscan.io/ was serious UX improvement, but wasn't broadly disseminated knowledge yet.
chas··on Coinbase Ventures
Yup, all-in the sign-up is roughly the same, the bills are pretty easy to keep paid, and fees are far less inconvenient than the possibility of losing control over a financially-significant private key.
chas··on Coinbase Ventures
“Very good UX” doesn’t really describe interacting with public cryptocurency networks for me between the security concerns, transaction times, and obscure address names. Is there a particular use case that you have in mind where that’s an improvement on the status quo from a UX perspective?
chas··on Ask HN: I don’t trust welding
Here's how engineers thinking about welding joints: https://www.youtube.com/watch?v=SZiEoN8tYvI

You'll note in those calculations that he assumes that the weld is basically the same as the base metal. As long as the weld is performed properly, the assumptions should hold to within a factor of safety.

For the relatively thin material used in cars and motorcycles, it doesn't take very long for the metal to melt all the way through in a single spot, so very strong welds can be created quickly. Further, between the skill of the fabricators and editing for TV, it is hard for someone without familiarity with welding to know what all is going into a joint just by watching the footage after.

Do you have a specific show in mind?

chas··on BOOM v2: an open-source out-of-order RISC-V core
Here's a collection of RISC-V cores in Bluespec: https://github.com/csail-csg/riscy
chas··on What Monoids teach us about software
Associative operators with an identity are extremely common in programming, inverses are much less common. Most ways to turn a lot of data into a little data have a monoid hidden in them with the identity serving as a default value in the case of missing data.

There is nothing you can comcatenate to a list to get the empty list, nothing you can OR with True to get False, and nothing you can union with a set to get the empty set.

chas··on What Monoids teach us about software
It's useful when you write functions that take generic monoids as arguments, such as many aggregation functions on data structures. For instance, finding the largest element in a tree, or the first successful result in a list of actions. Structuring the code like this separates the concerns of traversing the data structure and performing the particular type of aggregation. Haskell has the function foldMap which implements this idea.

If this is interesting to you Dan Piponi goes into significantly more detail (http://blog.sigfpe.com/2009/01/haskell-monoids-and-their-use...).

chas··on Sweet.js – Hygienic Macros for JavaScript
I have used it recently. I have a similar attitude towards m4 as shell scripts: they are good for quick hacks, proofs of concept, and very simple systems. When I need to sprinkle just a bit of macros on something, m4 is great. For example, a one-off piece of technical documentation I wrote is markdown interspersed with code examples. I wanted to make sure the code passed its unit tests, so it lives in separate files and I use m4 to include it into the bigger document. This is nicer than catting separate file chunks together because the text can all be contiguous, but if I needed to do anything more sophisticated I would probably switch to purpose-built templating or static site system.
chas··on Introducing Keras 2
Which research are you referring to?
chas··on Abstract Algebra (2016) [pdf]
I think that Abstract Algebra has the same relationship with CS as Linear Algebra has with the theory of most engineering disciplines. That is to say that in computer science, Abstract Algebra is the natural setting to define and decompose problems and design their solutions. For a specific example, CRDTs are a fundamentally algebraic approach to problem solving in computer science. They were discussed recently on HN here. [0] If you want to go further down that rabbit hole, Joseph Goguen spent a large portion of his career working on applications of Abstract Algebra to computer science. He produced a category-theory-focused introduction here. [1]

[0] https://news.ycombinator.com/item?id=13803843 [1] https://www.cs.ox.ac.uk/files/3395/PRG72.pdf

chas··on Deep Learning enables hearing aid wearers to pick out a voice in a crowded room
This approach surprised me. Why are they doing feature extraction and then feeding that into a DNN? It seems much more straightforward to have the input of the network be noisy samples and the output be clean samples a la super resolution[0] in images. They probably wouldn't want to use fully-connected layers in that instance, but I don't see any fundamental barriers if they have enough computational power to run a neural network already. Am I missing something?

[0] https://arxiv.org/pdf/1603.08155.pdf

chas··on The Alien Style of Deep Learning Generative Design
With the exception of the antennas designed with genetic algorithms[0], the "alien" aesthetic in all of these examples looks like the output of topological optimization tools. For example: https://www.youtube.com/watch?v=igRFFMSfwSQ

They emphasize that Dreamcatcher uses a "top-down" style of design, so maybe they are using deep learning for NLP to parse requirements and then feeding those requirements into normal topological optimization tools?

[0] https://ti.arc.nasa.gov/m/pub-archive/1244h/1244%20(Hornby).... (pictures from their post on page 5)

chas··on A Symbolic Analysis of Relay and Switching Circuits (1936) [pdf]
Not web development per se, but Clos Networks[0] were originally designed for telephone systems and re-emerged in large datacenter networks[1].

[0] https://en.wikipedia.org/wiki/Clos_network

[1] http://research.google.com/pubs/pub43837.html

chas··on Epiphany-V: A 1024-core 64-bit RISC processor
It is[0] and electrical engineering students make them pretty regularly, it's just much more expensive and complicated if you actually want to make a chip with the output of one instead of just simulating it.

[0]https://www.coursera.org/learn/vlsi-cad-logic

chas··on Neural network spotted deep inside Samsung's Galaxy S7 silicon brain
Yes. Most neural net applications separate training and inference so that once the net is in production it doesn't change, though it might be replaced with a new net rather frequently depending on how much the distribution of data it's operating on changes over time.
chas··on How we used Category Theory to solve a problem in Java
Yes! This isn't an accident. Erik Meijer, who contributed extensively to the Reactive Framework at Microsoft, has been very vocal about his use of category theory for software design. (https://www.youtube.com/watch?v=JMP6gI5mLHc) He currently runs Applied Duality which is uses category theory as its guiding design principle (http://www.applied-duality.com/)
chas··on Watch a Computer Made Out of Dominoes Do Basic Math
If you are interested in non-electronic digital computers you might want to check out this previous discussion:(https://news.ycombinator.com/item?id=7824588)

If you are particularly interested in domino logic and adders, baddox posted this video (https://www.youtube.com/watch?v=SudixyugiX4), petercooper posted this one (https://www.youtube.com/watch?v=lNuPy-r1GuQ) by Matt Parker (the same guy in this video) and I documented a 2-bit build I did (http://imgur.com/a/qq7Kl).

chas··on A difference between Haskell and Common Lisp
Speaking of things that the Haskell type system lets you make explicit, the isomorphism between streams and functions from the natural numbers means that streams are "representable functors" in the jargon of category theory. [1] Knowing that a data type is representable allows you to immediately build a bunch of other interesting structures on the data type. [0]

[0] http://covariant.me/notes/rep-functors.html [1] https://pamiz.wordpress.com/2014/02/13/the-functor-of-infini...

← PreviousPage 3 of 6Next →