Replies

koz, to haskell
@koz@chaos.social avatar

Someone who knows and ML: is there a writeup somewhere explaining how first-class modules (a la ML) can do similar things to Haskell type classes? I'm finding it hard to figure that out.

To give a more concrete case: suppose I wanted to write something like Control.Applicative, which provides an 'interface' Applicative with some methods, as well as functions that work for any Applicative. How would I do this with ML-style first-class modules?

jaror,
jaror avatar

@koz I would like to see such a comparison post too. In the meantime I found this stackoverflow question which contains a way to do it using an ML functor: https://stackoverflow.com/questions/48989663/monads-and-sml-modules. The obvious downside is that you have to explicitly state which monad to use at some point.

Another lesser known difference is that I believe you can't instantiate an ML signature with a polymorphic type. For example you can't write an instance of that MAPPABLE signature for a type like Map k v. At least not such that it is still polymorphic over the key type k.

DiazCarrete, to haskell
@DiazCarrete@hachyderm.io avatar
jaror,
jaror avatar

@DiazCarrete That slide seems to misrepresent effect systems. It is easy to replace just runInputConst:

runAllEffects (runInputDifferently program)

The runInputDifferently effect handles the Input Config effect and it leaves an unused Input Config in the list of effects. So the runInputConst config handler in runAllEffects will not be used.

jaror, to haskell
jaror avatar

Declarative vs imperative:

let v = sum [ ((x ! i) - m) ^ 2 | i <- [0 .. cc - 1] ] / fromIntegral cc
float v = 0.0f;
for (int i = 0; i < C; i++) {
    float xshift = x[i] - m;
    v += xshift * xshift;
}
v = v/C;
jaror,
jaror avatar

Admittedly it gets more complicated when summing two things at the same time:

let Pair dnormMean dnormNormMean = 
      fold (Pair <$> dimap (\(Pair _ dnormI) -> dnormI) (/ fromIntegral cc) sum
                 <*> dimap (\(Pair normBti dnormI) -> normBti * dnormI) (/ fromIntegral cc) sum)
        $ map (\i -> Pair (((inp ! (off + i)) - meanBt) * rstdBt)
                          ((weight ! i) * (dout ! (off + i))))
          [0 .. cc - 1]
float dnorm_mean = 0.0f;
float dnorm_norm_mean = 0.0f;
for (int i = 0; i < C; i++) {
    float norm_bti = (inp_bt[i] - mean_bt) * rstd_bt;
    float dnorm_i = weight[i] * dout_bt[i];
    dnorm_mean += dnorm_i;
    dnorm_norm_mean += dnorm_i * norm_bti;
}
dnorm_mean = dnorm_mean / C;
dnorm_norm_mean = dnorm_norm_mean / C;
someodd, to haskell
@someodd@fosstodon.org avatar

Please share with me your wisdom on packaging and distributing software made with .

jaror,
jaror avatar

@someodd Also note that the advice is about Stackage and not Stack. You can use Stackage snapshots with Cabal. E.g. you can create a cabal.project file with a line like this: import: https://www.stackage.org/lts-22.16/cabal.config. It still has a lot of rough edges, for example it is not possible to override specific constraints from the snapshots, but it is usable.

@simonmic

someodd, to haskell
@someodd@fosstodon.org avatar

Could I get some love, please?

I feel I'm developing lots of software in for and cool things.

A showcase of some of my projects: https://www.someodd.com/showcase

My GitHub (please follow, star): https://github.com/someodd

jaror,
jaror avatar

@someodd Your showcase website times out for me.

jaror,
jaror avatar

@someodd That page loads instantly.

jaror,
jaror avatar

@someodd I see it is just the .com domain that is problematic. The https://www.someodd.zip/showcase does load fine.

jaror,
jaror avatar

@someodd Yeah, I think kbin.social doesn't federate edits yet.

mangoiv, (edited ) to haskell
@mangoiv@functional.cafe avatar

Is it just me or is this whole thing about „don’t do X if you don’t really know what you’re doing“ really counter productive? Many people live in fear of X now and don’t start thinking if X is an actual problem or learn what the problems are that could rise from X.

I see this very often in the ecosystem where the solution to doing X properly is often learnt in a few minutes investigation.

jaror,
jaror avatar

@mangoiv I know I've said that a few times. Two examples I can think of:

  • AllowAmbiguousTypes, GHC suggests this but you should probably just use Proxy arguments instead.
  • Typeable, people coming from OOP languages often want a typeof function, but 99% of the time there is a better way to structure your programs using simple ADTs.

I still think these are not learnt in a few minutes. Even if that was the case, the most important thing you should learn is that you shouldn't use them very often.

pmidden, to haskell
@pmidden@fosstodon.org avatar

TIL about MicroHs, an alternative compiler that can compile Haskell2010 https://hackage.haskell.org/package/MicroHs-0.9.8.0

jaror,
jaror avatar

@pmidden There's also a recording of Lennart Augustsson talking about how and why he made it: https://www.youtube.com/watch?v=Zk5SJ79nOnA

someodd, to haskell
@someodd@fosstodon.org avatar

I don't understand why nixpkgs GHC 9.0.2 can seem to access base versions BEFORE 4.15, but the ghcup installed version cannot.

Help people!

jaror,
jaror avatar

@someodd What do you mean by "access"? GHC versions and base versions are tightly connected. GHC 9.0.2 is tied to base 4.15.1.0 (source). There is no way (yet) to change the base version used by GHC.

mangoiv, to haskell German
@mangoiv@functional.cafe avatar

GHC2024 has landed on HEAD and will be part of GHC 9.10, notable changes include:

  • GADTs + MonoLocalBinds
  • DataKinds
  • LambdaCase

Sadly no BlockArguments (Haskeller appear to love their dollars) and TypeData (time hasn’t come I guess)

Also thank god no ImpredicativeTypes and TypeFamilies

https://gitlab.haskell.org/ghc/ghc/-/merge_requests/12084

Also please thank @nomeata for pushing this forward! 👏

jaror,
jaror avatar

@mangoiv what's bad about ImpredicativeTypes?

mangoiv, (edited ) to random
@mangoiv@functional.cafe avatar

what would interest me is; how do you actually transfer imperative datastructures to functional ones; I have made the experience, that there are some mutable datastructures that are hard to find replacements for and one of them I once got so stuck on that I gave up finding an alternative for.

If you wanna riddle yourself, then here are the requirements: random access in O(1), including updatescons and snoc in O(1)

The imperative version of that datastructure is a simple mutable doubly list; random access is done by storing the pointers to the places you want to access and then just mutating the parts of the list in place; snoc and cons are just inserting a new element.

Thanks for the video again @kosmikus :)

https://www.youtube.com/watch?v=WHVMjMIJnB4

jaror,
jaror avatar

@mangoiv RE: "random access is done by storing the pointers to the places you want to access", that's not what I would consider random access, because if you want to be able to access any place in the list then you'd need to store all those pointers in an array and then you run into problems when you want to cons and uncons things in that array. So your proposed mutable solution only gives you random access for a select group of pointers, which cannot be changed in constant time.

I believe it is possible to generalise immutable fingertrees to have an arbitrary amount of "fingers" instead of just the one at the beginning and the one at the end of the sequence. That data structure would give you the same operations.

DiazCarrete, to haskell
@DiazCarrete@hachyderm.io avatar
jaror,
jaror avatar

@DiazCarrete I don't think I'd want to change the string type that often, but being able to make it be a specific type instead of having it be overloaded would be nice.

jaror, to haskell
jaror avatar

I enjoyed the simplicity of this recent Computerphile video on web servers: https://www.youtube.com/watch?v=7GBlCinu9yg

I attempted to recreate it in , but we don't really have a library on the same level of abstraction. wai is too abstract and network is not abstract enough.

jaror,
jaror avatar

We can make it a lot more performant, shorter, and also safer by using lazy byte strings:

{- cabal:
build-depends: base, network, network-run, bytestring
-}

{-# LANGUAGE OverloadedStrings #-}

import Network.Run.TCP (runTCPServer)
import qualified Network.Socket.ByteString.Lazy as Net
import qualified Data.ByteString.Lazy.Char8 as Str

main = runTCPServer (Just "127.0.0.1") "9999" $ \s -> do
  request <- Net.getContents s
  case Str.words (Str.takeWhile (/= '\r') request) of
    ["GET", resource, "HTTP/1.1"] -> do
      let path = Str.concat 
            [ "htdocs/"
            , Str.dropWhile (== '/') resource
            , if Str.last resource == '/' then "index.html" else ""
            ]
      page <- Str.readFile (Str.unpack path)
      Net.sendAll s ("HTTP/1.1 200 OK\r\n\r\n" <> page)
    _ -> error "todo"
  • All
  • Subscribed
  • Moderated
  • Favorites
  • megavids
  • thenastyranch
  • rosin
  • GTA5RPClips
  • osvaldo12
  • love
  • Youngstown
  • slotface
  • khanakhh
  • everett
  • kavyap
  • mdbf
  • DreamBathrooms
  • ngwrru68w68
  • provamag3
  • magazineikmin
  • InstantRegret
  • normalnudes
  • tacticalgear
  • cubers
  • ethstaker
  • modclub
  • cisconetworking
  • Durango
  • anitta
  • Leos
  • tester
  • JUstTest
  • All magazines