PureScript 无法将 Maybe Int 类型与 Int 类型匹配

PureScript Could not match type Maybe Int with type Int

我正在做书上的作业"PureScript by example"使用递归来计算数组中偶数项的数量。

这是我写的代码

isEven :: Int -> Boolean
isEven 0 = true
isEven 1 = false
isEven n = isEven(n - 2) 

countEven :: List Int -> Int
countEven list = 
   if null list 
   then 0
   else 
      if isEven(unsafePartial (head list)) 
      then 1 
      else 0 + countEven(unsafePartial (tail list))

我收到一条错误消息说

Error found:
in module Main
at src/Main.purs line 74, column 17 - line 74, column 42

  Could not match type

    Maybe Int

  with type

    Int


while checking that type t0
  is at least as general as type Int
while checking that expression unsafePartial (head list)
  has type Int
in binding group countEven

我有点意外,因为unsafePartial head list的数据类型是Int,unsafePartial tail list是List Int

那为什么感觉某处有Maybe呢?

您收到此错误的事实意味着您正在使用 Data.List 中的 head and tail,这实际上不是部分的,而是 return 和 Maybe .

要使用它们的部分副本,请从 Data.List.Partial 导入它们。

你应该使用uncons而不是像unsafePartial这样的重锤,因为它很容易从你的手中滑落...

如果你真的想手写这个递归(我认为这是一种反模式)你可以这样写:

module Main where

import Data.Array (uncons)
import Data.Maybe (Maybe(..))

isEven :: Int -> Boolean
isEven n = n `mod` 2 == 0

countEven l =
  case uncons l of
    Just { head, tail } ->
      let
        s =
         if isEven head
         then 1
         else 0
      in
        s + countEven tail
    Nothing -> 0

这是 try.purescript.org 上此片段的交互式版本。

正如我上面所说,您应该避免使用 unsafePartialPartial,因为它们会破坏您对程序整体性的信心。完整性是任何程序的真正有价值的功能。 总的来说,我认为使用 foldfoldMap + ala 等高级工具比 "raw recursion assembly".

要好得多