Why a torrent scraper? Don’t trust any “solutions” Want to run this on a VPS (with just Node) Just need magnet links downloaded Don’t want to do this manually I’m forgetful (want to run on CRON, etc)
Callback JS soup version (Worst of all worlds) RxJS version, JS still sucks Node + Elm version Elm for logic, but mechanics still separate and Rx powered Still requires startup of Elm runtime Ports interface still not so great Written in 0.16, 0.17 removed Signals, upgrade woes Previous versions?
Why Purescript? Want more compiler-checked code Want real FFI Want main program mechanics to not be in JS Signals (FRP library in Elm) removed in 0.17, making interfacing and writing programs more annoying Want to remove more of my own code as I can Purescript is way cooler
Quick introduction to PS FP lang inspired by Haskell Some big usability improvements Compiles to legible, real JS with no runtime Gives you real FFI More granular “Effects” system compared to Haskell’s “IO” main :: forall e. Eff (err :: EXCEPTION, get :: HTTP, post :: HTTP, console :: CONSOLE | e) Unit
Porting Elm to PS Most Elm code stays the same (other than :/::, Elm List -> JS/PS Array), but gets suped-up Get to use real FFI, no awkward runtime/port interface Control through Aff (async effects, basically `ErrorT (ContT Unit (Eff e) a`) Typeclasses like Functor (aka Interfaces like IMappable) Introduce fine-grained Effects
Typeclasses Programming to interfaces with generic types is awesome But can’t do non-built-in comparable types in Elm E.g. how do you make a Set with generic types? Elm: Instantiate collection w/ concrete ordering/compare function? https://github. com/eeue56/elm-all-dict Purescript: Use a collection using the Ord typeclass, then derive or implement Ord (like purescript- sets) OR Roll your own collection easily, define your own typeclass, have instances to back it
Creating/Using Typeclasses foreign import data CrappyHashSet :: * -> * class CrappyHash a where crappyHash :: a -> String data Coords = Coords Int Int instance crappyHashCoords :: CrappyHash Coords where crappyHash (Coords x y) = "x:" ++ (show x) ++ "y:" ++ (show y) foreign import empty :: forall a. CrappyHashSet a foreign import insert :: forall a. (CrappyHash a) => a -> CrappyHashSet a -> CrappyHashSet a foreign import mapToArray :: forall a b. (a -> b) -> CrappyHashSet a -> Array b
Functor - “Functors can be thought of as homomorphisms between categories.” - Wikipedia Homomorphisms - “Structure-preserving operation”, i.e. map Categories - “‘Arrow’”-linked ‘objects’”, e.g. array (infix map) - “I am a LOW priority operator for which I take the function on my left and map it to the thing on my right” Can be used with anything with an instance of Functor defined instance functorAff :: Functor (Aff e) where map f fa = [...] class Functor f where map :: (a -> b) -> f a -> f b
Results ✓ Works when source compiles ✓ Real FFI, no more runtime/port interfaces ✓ Contains the main mechanics of the program ✓ Can write code to typeclasses and their instances ✓ JS code reduced/minimized ✓ Is cool