Haskell,graph,将函数放入最通用的形式 - > Eq

Die*_*ter 0 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
Run Code Online (Sandbox Code Playgroud)

最后,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
Run Code Online (Sandbox Code Playgroud)

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

scv*_*lex 8

对于初学者来说,你无法概括Int为a Eq a的原因是因为999硬编码check.如果你只是在那里留下一些随机值,你必须知道它的类型,所以你不能概括超出它的功能(嗯,在这种特殊情况下,你可以推广到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
Run Code Online (Sandbox Code Playgroud)

这里的想法是,如果它找不到任何东西,或者它找到23(或它找到的任何东西),则findNeighbour返回.NothingJust 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
Run Code Online (Sandbox Code Playgroud)

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

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

  • +1很好的答案,但我有一个挑剔:`999`不是'Int`,而是'Num a => a`,所以可以概括为`Eq a,Num a => ... `只需删除原始版本的类型签名即可. (2认同)