我正在“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
那为什么感觉到某个地方有一个可能?
答案 0 :(得分:7)
您收到此错误的事实意味着您正在使用Data.List
中的head
和tail
,这些Maybe
实际上并不是部分错误,而是返回{ {1}}。
要使用部分对应部分,请从Data.List.Partial
导入。
答案 1 :(得分:1)
你应该使用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上此代码段的互动版本。
正如我上面所说,你应该避免使用unsafePartial
和Partial
,因为它们会破坏你对程序整体的信心。 Totality是任何程序的非常有价值的功能。
总的来说,我认为使用更高级别的工具(例如fold
或foldMap
+ ala
比“原始递归程序集”更好。