Skip to content

Instantly share code, notes, and snippets.

View ramirez7's full-sized avatar
๐Ÿ’—
Grey hairs are visible / I'm kinda of miserable, too

Armando Ramirez ramirez7

๐Ÿ’—
Grey hairs are visible / I'm kinda of miserable, too
View GitHub Profile
@ramirez7
ramirez7 / package-import-nix-shell.sh
Last active September 21, 2022 20:37
parse-package-imports.sh
#! /usr/bin/env bash
set -euo pipefail
shopt -s inherit_errexit
packagesRaw=$(./parse-package-imports.sh $1)
shift
readarray -t foundPackages <<< "$packagesRaw"
nix="haskellPackages.ghcWithPackages (pkgs: with pkgs; [ ${foundPackages[@]} ])"

I've written a few FFI bindings that I use for my games:

  • cute-c2-hs and cute-sound-hs - These are bindings to single-header C libraries. The header itself is included in the git repo.
  • sdl-gpu-hs - This C/C++ library is not included in the repo. It is declared as a dependency via pkgconfig-depends in the .cabal file.

Some general tips I've picked up:

  • hsc2hs works great. It doesn't do much for you, but it give you a nice way to create safe bindings.
  • Try to make your binding as "literal" as possible. You will end up with a lot of boilerplate, but it' a good starting point.
    • You can embed any C function in Haskell with basically 0 overhead by using raw Ptrs and primitives.
  • After you have the verbatim C binding, you can build higher-level bindings. I like to make "simple" bindings next - they hide the Ptr allocation and poke-ing with a litt
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-
Here are the GHC/singletons versions I used to run this:
class HasNone (b :: Type) (fe :: Type -> Effect) (es :: [Effect])
instance TypeError
('Text "Found The " ':<>: 'ShowType fe ':<>: 'Text " twice:" ':$$:
'Text "" ':$$:
'Text "* " ':<>: 'ShowType (fe a) ':$$:
'Text "* " ':<>: 'ShowType (fe b)
) => HasNone b fe (fe a : es)
instance {-# OVERLAPPABLE #-} HasNone b fe es => HasNone b fe (_1 : es)
instance HasNone _1 _2 '[]
data GDebug :: Effect where
GDebug :: Loc -> Shape -> GDebug m ()
runGraphicalDebug :: GPU :> es => Eff (GDebug : es) -> Eff es
data GPU :: Effect where
-- Platform-independent, general-purpose graphics primitives go here
runGPU'GL :: Reader GL.Context :> es => Eff (GPU : es) -> Eff es
runGPU'VK :: Reader VK.Context :> es => Eff (GPU : es) -> Eff es
{-# LANGUAGE TemplateHaskell #-}
module Cleff.Apecs where
import Cleff
import Apecs qualified as Upstream
data ApecsE world :: Effect where
LiftApecs :: Upstream.SystemT world m a -> ApecsE world m a
runApecs :: IOE :> es => world -> Eff (ApecsE world : es) a -> Eff es a

Tested on a System76 Lemur Pro.

  1. Download installation iso onto USB
    • sudo dd if=~/Downloads/nixos-plasma5-21.11.335288.3ddd960a3b5-x86_64-linux.iso of=/dev/sdc1
      • Make sure the output is the right device!
    • I used the KDE Plasma graphical image.
  2. Boot laptop into it
    • Hold ESC on startup according to this
    • Select "One Time Boot" and "Boot from USB".
  • That boots into grub. Was able to boot into the live usb with some commands from this blog
// Kotlin implementation of `fix`
// https://hackage.haskell.org/package/base-4.15.0.0/docs/Data-Function.html#v:fix
//
// Note the use of `Lazy`. It is the key to this working at all - without it, we
// spin until we get a stack overflow.
fun <A> fix(f: (Lazy<A>) -> A): A =
object {
val x: A by lazy {
f(lazy { this.x })
}
fun <A> trace(a: A): A {
println(a)
return a
}
fun <A, B> named(a: A, b: B) {}
fun main(args: Array<String>) {
named(a = trace("it's"), b = trace("belphegor"))
@ramirez7
ramirez7 / impbcopy.m
Created May 12, 2021 18:12
impbcopy - pbcopy but properly copies images
// From http://www.alecjacobson.com/weblog/?p=3816
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <unistd.h>
BOOL copy_to_clipboard(NSString *path)
{
// http://stackoverflow.com/questions/2681630/how-to-read-png-image-to-nsimage
NSImage * image;
if([path isEqualToString:@"-"])