Haskell,图,把函数放到最一般的形式 - >公式

时间:2012-11-22 23:26:28

标签: haskell

我想将2个函数(colorcheck)放入最通用的形式 Eq a => ...。 但我不知道该怎么做。

这是一个非常简单的图:每个节点有2个邻居,任何相邻的节点必须有不同的颜色

color ::  [(Int, Int)] -> [(Int, Int)] -> Bool
color x [] = True
color a ((x,y):rest) =
    if check a x == check a y
    then False
    else color a rest

check :: [(Int, Int)] -> Int -> Int
check [] x = 999
check ((x,y):rest) p =
    if x == p
    then y
    else check rest p

最后,colors会为您提供TrueFalse

Main> colors [('a',"purple"),('b',"green"),('c',"blue")] [('a','b'),('b','c'),('c','a')]
True

Main> colors [('a',"purple"),('b',"green"),('c',"purple")] [('a','b'),('b','c'),('c','a')]
False

Main> colors [('1',"purple"),('2',"green"),('3',"blue")] [('1','2'),('2','3'),('3','1')]
True

Main> colors [('1',"4"),('2',"5"),('3',"6")] [('1','2'),('2','3'),('3','1')]
True

Main> colors [('1',"4"),('2',"4"),('3',"5")] [('1','2'),('2','3'),('3','1')]
False

欢迎任何帮助(+如果您可以将x = 999修复为False)。

1 个答案:

答案 0 :(得分:8)

对于初学者,您无法将Int概括为Eq a的原因是因为check中的999硬编码。如果你只是在那里留下一些随机值,你必须知道它的类型,所以你不能概括除此之外的函数(在这种特殊情况下,你可以推广到Eq a, Num a,但是不多了)。

所以,答案是不使用某些任意值,而是将check的返回包装成一个具有“失败”情况的类型,即Maybe

重命名变量以遵循Haskell约定,并为函数提供更多阐述名称,我们得到:

canColor ::  Eq a => [(a, a)] -> [(a, a)] -> Bool
canColor _ [] = True
canColor xs ((x,y):rest) =
    if findNeighbour xs x == findNeighbour xs y
    then False
    else canColor xs rest

findNeighbour :: Eq a => [(a, a)] -> a -> Maybe a
findNeighbour [] _ = Nothing
findNeighbour ((x,y):rest) z =
    if x == z
    then Just y
    else findNeighbour rest z

这里的想法是findNeighbour如果找不到任何内容则会返回Nothing,如果找到23(或找不到任何内容),则会Just 23

碰巧,findNeighbour已经定义:它被称为lookup。因此,您可以将代码重写为:

canColor ::  Eq a => [(a, a)] -> [(a, a)] -> Bool
canColor _ [] = True
canColor xs ((x,y):rest) =
    if lookup x xs == lookup y xs
    then False
    else canColor xs rest

现在,我们注意到您基本上是针对列表中的所有项目检查谓词。这有一个功能:all。因此,我们可以将代码缩短为:

canColor ::  Eq a => [(a, a)] -> Bool
canColor xs = all (\(x, y) -> lookup x xs /= lookup y xs) xs