这是我的功能
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中重新定义函数签名,有没有办法解决这个问题?
答案 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]]]]]]