Variadic list constructor, how to default to the correct type and get type safety

China☆狼群 提交于 2019-11-30 20:51:33

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"
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!