Here\'s what I\'ve got:
{-# LANGUAGE MultiParamTypeClasses
, FlexibleInstances #-}
class ListResultMult r a where
lstM :: a -> [a] -> r
Type functions seem like just the ticket for this problem. Here's a sample file:
{-# LANGUAGE TypeFamilies #-}
class ListResultMult r where
type Elem r
lstM :: Elem r -> [Elem r] -> r
listM a = lstM a []
instance (ListResultMult r, Elem r ~ a) => ListResultMult (a -> r) where
type Elem (a -> r) = a
lstM a as x = lstM x (a:as)
instance ListResultMult [a] where
type Elem [a] = a
lstM a as = reverse (a:as)
Here are your examples in ghci:
*Main> listM 'a' 'b' 'c' :: String
"abc"
*Main> putStrLn $ listM 'a' 'b' 'c'
abc
*Main> listM 1 2 :: [Int]
[1,2]
*Main> sum $ listM 1 2
3
*Main> listM 1 :: [Int]
[1]
*Main> :t listM 'a' True
<interactive>:1:7:
Couldn't match type `Bool' with `Char'
In the first argument of `listM', namely 'a'
In the expression: listM 'a' True
*Main> :t listM 2 "foo"
<interactive>:1:7:
No instance for (Num [Char])
arising from the literal `2'
Possible fix: add an instance declaration for (Num [Char])
In the first argument of `listM', namely `2'
In the expression: listM 2 "foo"