如何实现Haskell中QTree类型的inQTree函数?解决参数不足问题
解决Haskell中inQTree的参数匹配问题
嘿,我完全懂你碰到的这个麻烦——核心问题就是数据构造器的参数形式和Either分支的结构没对上,咱们一步步理清楚:
先复盘下你的类型定义和目标函数:
data QTree a = Cell a Int Int | Block (QTree a) (QTree a) (QTree a) (QTree a)
Cell需要三个独立参数:a、Int、Int;Block需要四个独立的QTree a参数。
而inQTree的输入类型是:
Either (a, (Int, Int)) (QTree a, (QTree a, (QTree a, QTree a)))
左边是嵌套二元组(a, (Int, Int)),右边是嵌套的四元组结构(QTree a, (QTree a, (QTree a, QTree a)))。你原来写的either Cell Block试图直接把构造器当参数传,但Cell要三个参数,可左分支只给了一个元组,自然会提示参数不足。
正确的实现方式
我们需要把嵌套元组拆解,把内部元素一一对应传给构造器,这里有两种直观的写法:
写法1:用Lambda表达式解构元组
inQTree = either (\(val, (row, col)) -> Cell val row col) (\(t1, (t2, (t3, t4))) -> Block t1 t2 t3 t4)
左边的lambda把(a, (Int, Int))拆成三个独立变量,刚好匹配Cell的参数需求;右边的lambda则把嵌套的四元组结构拆成四个QTree a,传给Block。
写法2:用模式匹配(可读性更强)
如果觉得lambda有点绕,直接用模式匹配写逻辑会更清晰:
inQTree (Left (val, (row, col))) = Cell val row col inQTree (Right (topLeft, (topRight, (bottomLeft, bottomRight)))) = Block topLeft topRight bottomLeft bottomRight
这种写法直接把Either的两个分支匹配出来,再把元组里的元素对应传给构造器,逻辑一目了然。
补充说明为什么原写法不行
either函数的类型是(a -> c) -> (b -> c) -> Either a b -> c,它要求第一个参数是接收左分支类型的单参数函数,第二个是接收右分支类型的单参数函数。但你的Cell是三参数函数,不是接收(a, (Int, Int))的单参数函数——必须先解构元组,把内部元素提取出来再传给构造器才行。
内容的提问来源于stack exchange,提问作者wvstealth
相关产品推荐
相关产品推荐

