diff --git a/src/lib.rs b/src/lib.rs
index 1667fcaaf1f01ac2533477e0678ed21b04c3b64e..266450dc0bc752c7e720448cc5534af689908723 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -114,8 +114,8 @@ pub enum IpTo {
     Method(Ident),
 }
 
-/// `$($Ident: $Ty > $Path,)*`
-pub type Ips = HashMap<Ident, (Ty, Path)>;
+/// `$($Ident: Ident ($Ty) -> $Ty )*`
+pub type Ips = HashMap<Ident, (Ident, Ty, Ty)>;
 
 /// `$($Ident: $Ty = $Expr < $Path,)*`
 pub type Ops = HashMap<Ident, (Ty, Expr, Path)>;
diff --git a/src/parse.rs b/src/parse.rs
index 7dff7806d479301a14151e78b95a8174f41b033d..b1bce2381a4d9c4c3b0979b402df8d1d204c759d 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -2,11 +2,13 @@ use std::collections::{HashMap, HashSet};
 use std::iter::Peekable;
 use std::slice::Iter;
 
-use syn::{self, DelimToken, Ident, IntTy, Lit, Path, Token, BinOpToken, TokenTree, Ty};
+use syn::{self, DelimToken, Ident, IntTy, Lit, Path, Token, BinOpToken,
+          TokenTree, Ty};
 
 use error::*;
 
-use {Cro, Ips, Ops, App, Idle, Init, Resources, Static, Statics, Task, Tasks, Expr};
+use {Cro, Ips, Ops, App, Idle, Init, Resources, Static, Statics, Task, Tasks,
+     Expr};
 
 /// Parses the contents of `app! { $App }`
 pub fn app(input: &str) -> Result<App> {
@@ -23,7 +25,8 @@ pub fn app(input: &str) -> Result<App> {
             "device" => {
                 ensure!(device.is_none(), "duplicated `device` field");
 
-                device = Some(::parse::path(tts).chain_err(|| "parsing `device`")?);
+                device =
+                    Some(::parse::path(tts).chain_err(|| "parsing `device`")?);
             }
             "idle" => {
                 ensure!(idle.is_none(), "duplicated `idle` field");
@@ -38,12 +41,15 @@ pub fn app(input: &str) -> Result<App> {
             "resources" => {
                 ensure!(resources.is_none(), "duplicated `resources` field");
 
-                resources = Some(::parse::statics(tts).chain_err(|| "parsing `resources`")?);
+                resources = Some(::parse::statics(tts).chain_err(
+                    || "parsing `resources`",
+                )?);
             }
             "tasks" => {
                 ensure!(tasks.is_none(), "duplicated `tasks` field");
 
-                tasks = Some(::parse::tasks(tts).chain_err(|| "parsing `tasks`")?);
+                tasks =
+                    Some(::parse::tasks(tts).chain_err(|| "parsing `tasks`")?);
             }
             _ => bail!("unknown field: `{}`", key),
         }
@@ -71,7 +77,11 @@ fn bool(tt: Option<&TokenTree>) -> Result<bool> {
 }
 
 /// Parses a delimited token tree
-fn delimited<R, F>(tts: &mut Peekable<Iter<TokenTree>>, delimiter: DelimToken, f: F) -> Result<R>
+fn delimited<R, F>(
+    tts: &mut Peekable<Iter<TokenTree>>,
+    delimiter: DelimToken,
+    f: F,
+) -> Result<R>
 where
     F: FnOnce(&[TokenTree]) -> Result<R>,
 {
@@ -137,9 +147,14 @@ fn idle(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Idle> {
                     path = Some(::parse::path(tts)?);
                 }
                 "resources" => {
-                    ensure!(resources.is_none(), "duplicated `resources` field");
+                    ensure!(
+                        resources.is_none(),
+                        "duplicated `resources` field"
+                    );
 
-                    resources = Some(::parse::resources(tts).chain_err(|| "parsing `resources`")?);
+                    resources = Some(::parse::resources(tts).chain_err(
+                        || "parsing `resources`",
+                    )?);
                 }
                 _ => bail!("unknown field: `{}`", key),
             }
@@ -188,7 +203,10 @@ fn resources(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Resources> {
         let mut tts = tts.iter().peekable();
         while let Some(tt) = tts.next() {
             if let &TokenTree::Token(Token::Ident(ref ident)) = tt {
-                ensure!(!idents.contains(ident), "ident {} listed more than once");
+                ensure!(
+                    !idents.contains(ident),
+                    "ident {} listed more than once"
+                );
 
                 idents.insert(ident.clone());
 
@@ -262,18 +280,20 @@ fn statics(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Statics> {
         let mut tts = tts.iter();
         while let Some(tt) = tts.next() {
             match tt {
-                &TokenTree::Token(Token::Ident(ref id)) if id.as_ref() == "static" => {}
+                &TokenTree::Token(Token::Ident(ref id))
+                    if id.as_ref() == "static" => {}
                 _ => {
                     bail!("expected keyword `static`, found {:?}", tt);
                 }
             }
 
             let tt = tts.next();
-            let ident = if let Some(&TokenTree::Token(Token::Ident(ref id))) = tt {
-                id
-            } else {
-                bail!("expected Ident, found {:?}", tt);
-            };
+            let ident =
+                if let Some(&TokenTree::Token(Token::Ident(ref id))) = tt {
+                    id
+                } else {
+                    bail!("expected Ident, found {:?}", tt);
+                };
 
             ensure!(
                 !statics.contains_key(ident),
@@ -334,22 +354,33 @@ fn task(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Task> {
                 "enabled" => {
                     ensure!(enabled.is_none(), "duplicated `enabled` field");
 
-                    enabled = Some(::parse::bool(tts.next()).chain_err(|| "parsing `enabled`")?);
+                    enabled = Some(::parse::bool(tts.next()).chain_err(
+                        || "parsing `enabled`",
+                    )?);
                 }
                 "path" => {
                     ensure!(path.is_none(), "duplicated `path` field");
 
-                    path = Some(::parse::path(tts).chain_err(|| "parsing `path`")?);
+                    path = Some(
+                        ::parse::path(tts).chain_err(|| "parsing `path`")?,
+                    );
                 }
                 "priority" => {
                     ensure!(priority.is_none(), "duplicated `priority` field");
 
-                    priority = Some(::parse::u8(tts.next()).chain_err(|| "parsing `priority`")?);
+                    priority = Some(::parse::u8(tts.next()).chain_err(
+                        || "parsing `priority`",
+                    )?);
                 }
                 "resources" => {
-                    ensure!(resources.is_none(), "duplicated `resources` field");
+                    ensure!(
+                        resources.is_none(),
+                        "duplicated `resources` field"
+                    );
 
-                    resources = Some(::parse::resources(tts).chain_err(|| "parsing `resources`")?);
+                    resources = Some(::parse::resources(tts).chain_err(
+                        || "parsing `resources`",
+                    )?);
                 }
                 _ => bail!("unknown field: `{}`", key),
             }
@@ -490,19 +521,48 @@ fn ips(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ips> {
                 ident
             );
 
+
             let tt = tts.next();
             if let Some(&TokenTree::Token(Token::Colon)) = tt {
             } else {
                 bail!("expected Colon, found {:?}", tt);
             }
 
-            let ty = ::parse::ty(&TokenTree::Token(Token::Gt), &mut tts)
-                .chain_err(|| format!("parsing `type` for {:?}", ident))?;
+            let tt = tts.next();
+            let meth =
+                if let Some(&TokenTree::Token(Token::Ident(ref id))) = tt {
+                    id
+                } else {
+                    bail!("expected Ident, found {:?}", tt);
+                };
 
-            let path = ::parse::path(&mut tts).chain_err(|| "parsing `path`")?;
-            tts.next();
+            //let ty_param: Result<Ty> =
+            let ty_param =
+                ::parse::delimited(&mut tts, DelimToken::Paren, |tts| {
+                    Ok(syn::parse_type(&format!("{}", quote!(#(#tts)*)))?)
+                })?;
+
+
+            let tt = tts.next();
+            //            let ty_return: Result<Ty> = Ok(syn::parse_type(&"()")?);
+            let ty_return: Result<Ty> = match tt {
+                Some(&TokenTree::Token(Token::Comma)) => {
+                    tts.next();
+                    Ok(syn::parse_type(&"()")?)
+                }
+                Some(&TokenTree::Token(Token::RArrow)) => {
+                    ::parse::ty(&TokenTree::Token(Token::Comma), &mut tts)
+                }
+                _ => bail!("expected `-> Type,' or `,` found {:?}", tt),
+            };
+
+            //let tt = tts.next();
+            //            if let Some(&TokenTree::Token(Token::Comma)) = tt {
+            //            } else {
+            //                bail!("expected Comma, found {:?}", tt);
+            //            };
 
-            ips.insert(ident.clone(), (ty, path));
+            ips.insert(ident.clone(), (meth.clone(), ty_param, ty_return?));
         }
         Ok(ips)
 
@@ -533,12 +593,14 @@ fn ops(tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ops> {
                 bail!("expected Colon, found {:?}", tt);
             }
 
-            let ty = ::parse::ty(&TokenTree::Token(Token::Eq), &mut tts)
-                .chain_err(|| format!("parsing `type` for {:?}", ident))?;
+            let ty =
+                ::parse::ty(&TokenTree::Token(Token::Eq), &mut tts)
+                    .chain_err(|| format!("parsing `type` for {:?}", ident))?;
 
 
-            let expr = ::parse::expr(&TokenTree::Token(Token::Lt), &mut tts)
-                .chain_err(|| format!("parsing `type` for {:?}", ident))?;
+            let expr =
+                ::parse::expr(&TokenTree::Token(Token::Lt), &mut tts)
+                    .chain_err(|| format!("parsing `type` for {:?}", ident))?;
 
 
 
@@ -573,7 +635,10 @@ fn ty(token: &TokenTree, tts: &mut Peekable<Iter<TokenTree>>) -> Result<Ty> {
 }
 
 /// Parses `$Expr `
-fn expr(token: &TokenTree, tts: &mut Peekable<Iter<TokenTree>>) -> Result<::Expr> {
+fn expr(
+    token: &TokenTree,
+    tts: &mut Peekable<Iter<TokenTree>>,
+) -> Result<::Expr> {
     let mut fragments = vec![];
     loop {
         if let Some(tt) = tts.next() {