{-# LANGUAGE TypeFamilies #-} class ProjResult a where projection :: Int -> a constant :: Int -> a instance ProjResult Int where projection _ = error "index too large" constant x = x instance (ProjResult a, arg ~ Int) => ProjResult (arg -> a) where projection 0 x = constant x projection n _ = projection (n-1) constant j _ = constant j p :: Int -> Int -> Int -> Int -> Int p = projection main = do print $ p 2 1 2 3 print (projection 2 1 2 3 :: Int) -- 型注釈はこれだけでいい