无法匹配打印嵌套列表的Haskell代码中的预期类型?

时间:2015-08-17 17:38:39

标签: haskell

这是我的功能

data Item a = One a | Many [Item a]
let flat (One x) = show x
let flat (Many xs) = show xs

这是输出

Prelude> flat [[3]]

<interactive>:21:6:
Couldn't match expected type ‘Item t0’ with actual type ‘[[t1]]’
In the first argument of ‘flat’, namely ‘[[3]]’
In the expression: flat [[3]]
In an equation for ‘it’: it = flat [[3]]

似乎flat不会将Item识别为其功能签名,所以我尝试重新定义函数签名

flat :: Item a -> [a]

<interactive>:22:1:
    Couldn't match type ‘a1’ with ‘Char’
  ‘a1’ is a rigid type variable bound by
       an expression type signature: Item a1 -> [a1] at  <interactive>:22:1
Expected type: Item a1 -> [a1]
  Actual type: Item a1 -> String
In the expression: flat :: Item a -> [a]
In an equation for ‘it’: it = flat :: Item a -> [a]

但是Haskell不允许你在ghci中重新定义函数签名,有没有办法解决这个问题?

2 个答案:

答案 0 :(得分:4)

flat [[3]]会产生类型错误。 [[3]]类型为Num a => [[a]],而不是Show a => Item a,您可以将其传递到flat

flat (Many [3])将返回"[3]"

答案 1 :(得分:1)

回答你在@jtobin的回答中提到的后续问题:是的,有一种方法可以自动检测[3]是否需要包含在Maybe构造函数中。但是,您可能需要添加类型注释(参见example以帮助Haskell找出要做的事情=。

我们从一堆语言扩展开始。

{-# LANGUAGE MultiParamTypeClasses  #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances      #-}

然后是您对Item的定义。

module Item where

data Item a = One a | Many [Item a]

我们介绍了一类可以归结为Item a的东西,并声明了两个实例:Many和实例。你可以看到我们现在有重叠的实例(例如Itemable [Int] [Int]),所以你在这里玩火。

class Itemable b a where
  item :: b -> Item a

instance Itemable b a => Itemable [b] a where
  item = Many . fmap item
instance Itemable a a where
  item = One

您最终可以将flat定义为首先将b转换为Item a然后展平它的函数:

flat :: Itemable b a => b -> [a]
flat = go . item where
  go (One a)   = [a]
  go (Many as) = concatMap go as

其作用如以下示例类型检查和评估[2,43,7,8,1]显示:

example :: [Int]
example = flat [[[[[[2::Int],[43]],[[7],[8]],[[1]]]]]]

但是,只要您尝试使用重叠的实例,它就会在您的脸上吹响。 E.g:

example' :: [[Int]]
example' = flat [[[[[[2::Int],[43]],[[7],[8]],[[1]]]]]]