Skip to content

Instantly share code, notes, and snippets.

@mgsloan
Last active July 28, 2021 03:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mgsloan/d1acbabd30d068ef7d3c13f49eb40894 to your computer and use it in GitHub Desktop.
Save mgsloan/d1acbabd30d068ef7d3c13f49eb40894 to your computer and use it in GitHub Desktop.
Simplified function composition with variadic 2nd function (simplified but only works well for monomorphic arguments)
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
-- https://gist.github.com/mgsloan/7100f55c6ec12be8776a1a1c347cf963
-- for a more complex version with better type inference.
--
-- It was initially surprising to me that this one doesn't need the
-- "closed type family" trick to direct which instance is used. On
-- further thought,
-- f is a function (a -> r) mapping the result type.
-- g is the input function type, before the result is mapped.
-- h is the output function type, after the result is mapped.
class MapResult f g h where
mapResult :: f -> g -> h
-- Handles the base case where g has been supplied all its arguments,
-- and so is a value of type r that can be passed to f.
instance MapResult (a -> r) a r where
mapResult f x = f x
-- Handles the recursive case where g and h are functions.
instance MapResult f g h => MapResult f (x -> g) (x -> h) where
mapResult f g = \x -> mapResult f (g x)
-- A few monomorphic functions to use below
intToString = show :: Int -> String
addInts = (+) :: Int -> Int -> Int
add3Ints = (\x y z -> x + y + z) :: Int -> Int -> Int -> Int
showAddNumbers :: Int -> Int -> String
showAddNumbers = mapResult intToString addInts
showAdd3Numbers :: Int -> Int -> Int -> String
showAdd3Numbers = mapResult intToString add3Ints
main :: IO ()
main = do
putStrLn (showAddNumbers 24 13)
putStrLn (showAdd3Numbers 24 13 36)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment