simpleShaderExplicit' :: (ShaderType -> a -> IO Shader)
                      -> a -> a -> ([String],[String])
                      -> IO ShaderProgram
simpleShaderExplicit' load vsrc fsrc names =
  do vs <- load VertexShader vsrc
     fs <- load FragmentShader fsrc
     p <- linkShaderProgram [vs,fs]
     throwError
     (attrs,unis) <- getExplicits p names
     return $ ShaderProgram (fromList attrs) (fromList unis) p

-- |Load a 'ShaderProgram' from a vertex shader source file and a
-- fragment shader source file. The active attributes and uniforms in
-- the linked program are recorded in the 'ShaderProgram'.
simpleShaderExplicit' :: (ShaderType -> a -> IO Shader)
                      -> a -> a -> ([String],[String])
                      -> IO ShaderProgram
simpleShaderExplicit' load vsrc fsrc names =
  do vs <- load VertexShader vsrc
     fs <- load FragmentShader fsrc
     p <- linkShaderProgram [vs,fs]
     throwError
     (attrs,unis) <- getExplicits p names
     return $ ShaderProgram (fromList attrs) (fromList unis) p

-- |Load a 'ShaderProgram' from a vertex shader source file and a
-- fragment shader source file. The active attributes and uniforms in
-- the linked program are recorded in the 'ShaderProgram'.
simpleShaderExplicit' load vsrc fsrc names =
  do vs <- load VertexShader vsrc
     fs <- load FragmentShader fsrc
     p <- linkShaderProgram [vs,fs]
     throwError
     (attrs,unis) <- getExplicits p names
     return $ ShaderProgram (fromList attrs) (fromList unis) p

-- |Load a 'ShaderProgram' from a vertex shader source file and a
-- fragment shader source file. The active attributes and uniforms in
-- the linked program are recorded in the 'ShaderProgram'.