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

use*_*526 1 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
Run Code Online (Sandbox Code Playgroud)

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

Sib*_*ibi 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]
Run Code Online (Sandbox Code Playgroud)

怎么样,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].