如何用PureScript将正负整数数组拆分为二元组形式的两个数组?
PureScript 拆分正负整数数组为 Tuple 的正确实现
原代码的问题
你提供的代码存在三个核心问题:
- 仅定义了
splitPosAndNeg的类型签名,但没有实现函数逻辑,编译器无法识别该函数的行为。 - PureScript 不允许在顶层直接使用
let绑定,必须将这类变量定义放在函数内部(比如main)或用=声明顶层常量。 - 多变量
let绑定的缩进不规范,同一级的绑定需要保持对齐。
用 Data.Array.partition 实现(推荐)
Data.Array中的partition函数完全适配这个场景,它的类型为:
partition :: forall a. (a -> Boolean) -> Array a -> Tuple (Array a) (Array a)
它接受一个判断谓词和目标数组,返回一个 Tuple:第一个元素是满足谓词的元素数组,第二个是不满足的元素数组。
完整实现示例
module Main where import Effect (Effect) import Effect.Console (log) import Data.Array (partition) import Data.Tuple (Tuple(..), fst, snd) import Data.Show (show) -- 定义拆分函数:正数放入第一个数组,非正数(含0、负数)放入第二个数组 splitPosAndNeg :: Array Int -> Tuple (Array Int) (Array Int) splitPosAndNeg = partition (\x -> x > 0) main :: Effect Unit main = do -- 方式1:直接解构Tuple let Tuple pos neg = splitPosAndNeg [1, -2, 3, -4, 5, -6, -7, 8] log $ "正数数组: " <> show pos log $ "负数数组: " <> show neg -- 方式2:先绑定Tuple,再用fst/snd提取元素 let splitResult = splitPosAndNeg [1, -2, 3, -4, 5, -6, -7, 8] pos' = fst splitResult neg' = snd splitResult log $ "正数数组(方式2): " <> show pos' log $ "负数数组(方式2): " <> show neg'
严格区分正/负(排除0)
如果需要完全排除0,只保留纯正数和纯负数数组,可以调整实现:
splitPosAndNeg :: Array Int -> Tuple (Array Int) (Array Int) splitPosAndNeg arr = Tuple pos neg where pos = filter (\x -> x > 0) arr neg = filter (\x -> x < 0) arr
手动递归实现(理解底层逻辑)
如果想手动实现拆分逻辑(对应书中Tuple章节的学习目的),可以用递归遍历数组:
splitPosAndNeg :: Array Int -> Tuple (Array Int) (Array Int) splitPosAndNeg = foldl go (Tuple [] []) where go :: Tuple (Array Int) (Array Int) -> Int -> Tuple (Array Int) (Array Int) go (Tuple pos neg) x | x > 0 = Tuple (x : pos) neg | x < 0 = Tuple pos (x : neg) | otherwise = Tuple pos neg -- 忽略0元素
注:上述用foldl遍历会让元素逆序加入数组,若要保持原数组顺序,可改用foldr或最后对数组执行反转操作。
内容的提问来源于stack exchange,提问作者maxloo
相关产品推荐
相关产品推荐

