为什么head的返回值隐式转换为Maybe?

时间:2014-06-26 01:42:07

标签: haskell

我刚刚开始学习Haskell,为了实践,我决定创建一个函数,它接受一个树,其元素有一个位置和大小,并返回位于某个位置的元素。我的代码如下所示:

import Data.List (dropWhile)

data Node = Node (Int,Int) (Int,Int) [Node] deriving(Eq, Show)

findNode :: (Int,Int) -> Node -> Maybe Node
findNode loc node@(Node (x, y) (width, height) []) = if loc >= (x, y) && loc <= (x+width, y+height) then Just node else Nothing
findNode loc node@(Node (x, y) (width, height) children) = 
    if loc >= (x, y) && loc <= (x+width, y+height)
        then if not $ null nodes then
            head nodes
        else
            Just node
    else Nothing
    where nodes = dropWhile (==Nothing) $ map (findNode loc) children

据我所知,此代码编译和运行完美,但我对一件事感到好奇,为什么head nodes可以接受而不是Just $ head nodes?

1 个答案:

答案 0 :(得分:6)

那是因为您的nodes类型为[Maybe Node]。您可以通过明确地对其进行批注并再次编译来验证它:

findNode loc node@(Node (x, y) (width, height) children) = 
  if loc >= (x, y) && loc <= (x+width, y+height)
  then
    if not $ null nodes
    then head nodes
    else Just node
  else Nothing
  where
    nodes = dropWhile (==Nothing) $ map (findNode loc) children :: [Maybe Node]

那么nodes[Maybe Node]类型怎么办?

map (findNode loc) children的类型为[Maybe Node]。 (一般地图类型为map :: (a -> b) -> [a] -> [b],在您的情况下,findNode loc的类型为Node -> Maybe Node,因此结果类型为[Maybe Node])。 dropWhile的类型为(a -> Bool) -> [a] -> [a]。在您的情况下,a已经Maybe Node,因此您的nodes类型为[Maybe Node]