Skip to content

Instantly share code, notes, and snippets.

View snowleopard's full-sized avatar

Andrey Mokhov snowleopard

View GitHub Profile
@gelisam
gelisam / Dag.hs
Created March 12, 2019 15:51
using indexed Monads to make illegal DAGs underrepresentable
{-# LANGUAGE FlexibleInstances, GADTs, MultiParamTypeClasses, RebindableSyntax #-}
import Data.Maybe
import Prelude (IO, putStrLn, ($), id, (.), fst, snd)
data Void
data Dag where
Dag :: Dag' a -> Dag
{-# LANGUAGE TypeOperators, PatternSynonyms, ExplicitNamespaces #-}
{-# LANGUAGE LambdaCase, BlockArguments #-}
module Select
( type (-?)(Fun, Const, Lazy, unLazy), ($?)
, Selective(..)
, select, branch, whenS, ifS, whileS, fromMaybeS
, (<||>), (<&&>), anyS, allS
, Monad(..)
) where
{-# LANGUAGE NoMonomorphismRestriction, FlexibleContexts, FlexibleInstances, DeriveFunctor #-}
import Data.Bool
import Data.Functor
import Data.Bifunctor
import Data.Function ((&))
import Data.Semigroup
import Control.Applicative
import Control.Monad
@ulysses4ever
ulysses4ever / select.hs
Created June 29, 2018 10:59
`Selective` exercise: `select` of `handle`
import Data.Either (either)
import Data.Functor ((<$>))
class Applicative f => Selective f where
handle :: f (Either a b) -> f (a -> b) -> f b
select :: Selective f =>
f (Either a b) -> f (a -> c) -> f (b -> c) -> f c
select e fa fb = handle (Left <$> e) (either <$> fa <*> fb)
{-# LANGUAGE GADTs, RankNTypes, TypeFamilies, DataKinds, PolyKinds, TypeOperators, ScopedTypeVariables #-}
-- Lots of ways you can phrase this, but this works for me
-- For folks who haven't seen it before, this is "the essence of the sum type" and sigma stands for sum.
-- You see it far more often in dependent types than elsewhere because it becomes a lot more pleasant to
-- work with there, but it's doable in other contexts too. Think of the first parameter to the data
-- constructor as a generalized "tag" as we talk about in "tagged union", and the second parameter is the
-- "payload". It turns out that you can represent any simple sum type you could write in Haskell this way
-- by using a finite and enumerable `f`, but things can get more unusual when `f` isn't either. In such
-- cases, it's often easier to think of this as the essence of existential types.

Build Systems à la Carte (feedback)

Awesome

  • Worded explanations for all code snippets
  • Excel is a wonderful choice for practical examples
  • Awesome typography & formatting

Suggestions

  • Kind signatures for the definition of Task (`c` and `f`)
    • Took me a few minutes to correctly infer the kinds in my head
    • Point to the later polymorphism section

Corrections

@sjoerdvisscher
sjoerdvisscher / laws.hs
Last active July 24, 2018 08:16
First class checkable laws using the free-functors package
{-# LANGUAGE
TypeFamilies
, KindSignatures
, ScopedTypeVariables
, ConstraintKinds
, FlexibleInstances
, FlexibleContexts
, DeriveGeneric
, DeriveAnyClass
, TypeApplications
@Gabriella439
Gabriella439 / fibonacci.hs
Created March 25, 2018 00:52
Efficient fibonacci numbers using infinite precision integer arithmetic
import Numeric.Natural (Natural)
import qualified Data.Semigroup
-- | @fibonacci n@ computes the @nth@ fibonacci number efficiently using infinite
-- precision integer arithmetic
--
-- Try @fibonacci 1000000@
fibonacci :: Natural -> Natural
fibonacci n = x01 (Data.Semigroup.mtimesDefault n m)
@Profpatsch
Profpatsch / simple-types.nix
Last active March 31, 2018 18:10
Simple type system for nix expressions, with scalars, nested types, products, sums and unions.
# A simple type system to check plain nix values
# and get detailed error messages on type mismatch.
#
# Contains support for
# scalars (simple values)
# recursive types (lists of t and attrs of t)
# products (attribute sets with named fields)
# sums (tagged unions where you can match on the different cases)
# unions (untagged unions of the specified types)
# We can’t type functions (lambda expressions). Maybe in the future.
@Profpatsch
Profpatsch / shake.hs
Created December 5, 2017 09:47
Abstraction in Shake
main = do
let buildDir = "_build"
-- how to express on a non-string level that everything should only ever be put into "_build"?
-- how to never repeat that information anywhere else, much less do problematic string operations
-- with the `"_build"` constant?
staticDir = "static"
staticFiles = map (staticDir <>) [ "foo" "bar" "baz" ]
(buildDir </> staticDir </> "*") %> \outFile ->
-- we only get `out`, which is some unknown string