| Safe Haskell | None |
|---|
Data.Implicit
Description
Data.Implicit provides both named and unnamed implicit parameters that
support default values (given by the Default class from the data-default
package). It makes no use of the ImplicitParams extension and instead
everything is done using type classes.
Here is an example of unnamed implicit parameters:
{-# LANGUAGE FlexibleContexts #-}
import Data.Implicit
putParam :: Implicit_ String => IO ()
putParam = putStrLn $ "Param was: " ++ show (param_ :: String)
We define putParam, which is a simple function which takes an implicit
parameter of type String, and prints it to the screen. The param_ function
is used to retrieve the unnamed implicit parameter of type String from
putParam's context. The type signature is necessary to force param_ to
return a String, as this cannot be inferred due to the polymorphism of
show.
>>>putParamParam was ""
This is how we call putParam without specifying its implicit parameters. If
an implicit parameter is left unspecified, its value is defaulted to def,
assuming that its type has a Default instance. If not, then it is a type
error not to specify the value of an implicit parameter.
>>>putParam $~ "hello, world"Param was "hello, world"
The operator $~ takes a function f and a value to which to set the
homotypic implicit parameter on f. It applies the implicit parameter to f
and returns the result. There is also a prefix version of $~ whose arguments
are flipped called setParam_.
Here is an example of named implicit parameters:
{-# LANGUAGE DataKinds, FlexibleContexts, RankNTypes #-}
import Data.Implicit
import Data.Proxy
putFooBar :: (Implicit "foo" String, Implicit "bar" String) => IO ()
putFooBar = do
putStrLn $ "foo was: " ++ show foo
putStrLn $ "bar was: " ++ show bar
foo :: Implicit "foo" String => String
foo = param (Proxy :: Proxy "foo")
bar :: Implicit "bar" String => String
bar = param (Proxy :: Proxy "bar")
setFoo :: String -> (Implicit "foo" String => a) -> a
setFoo = setParam (Proxy :: Proxy "foo")
setBar :: String -> (Implicit "bar" String => a) -> a
setBar = setParam (Proxy :: Proxy "bar")
The Implicit constraint is the named equivalent of Implicit_. It takes an
additional argument of kind Symbol (which requires the DataKinds
extension; see the GHC.TypeLits module) to specify the name of the implicit
parameter. param and setParam work like their unnamed counterparts
param_ and setParam_, but they also take a proxy argument to specify the
name of the implicit parameter. The code above defines the wrappers foo and
bar and setFoo and setBar around param and setParam respectively,
which hide all the (slightly ugly) proxy stuff.
>>>putFooBarfoo was: "" bar was: ""
Once again, the defaults of unspecified implicit parameters are given by the
Default class.
>>>setFoo "hello, world" putFooBarfoo was: "hello, world" bar was: ""
>>>setBar "goodbye" $ setFoo "hello, world" putFooBarfoo was: "hello, world" bar was: "goodbye"
An infix version of setParam is also provided, $$~. Using $$~, the above
example would be:
>>>putFooBar $$~ (Proxy :: Proxy "foo", "hello, world") $$~ (Proxy :: Proxy "bar", "goodbye")foo was: "hello, world" bar was: "goodbye
Documentation
The constraint on a function Implicit "foo" Stringf indicates
that an implicit parameter named "foo" of type String is passed to
f.
The name "foo" is a type of kind Symbol (from the GHC.TypeLits
module). The DataKinds extension is required to refer to Symbol-kinded
types.
setParam :: proxy s -> a -> (Implicit s a => b) -> bSource
setParam supplies a value for an implicit parameter named s to a
function which takes a homotypic and homonymous implicit parameter. The
name s is specified by a proxy argument passed to setParam.
($$~) :: (Implicit s a => b) -> (proxy s, a) -> bSource
An infix version of setParam with flipped arguments.
type Implicit_ = Implicit AnySource
The constraint on a function Implicit_ Stringf indicates that an
unnamed implicit parameter of type String is passed to f.