You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell字符串字符替换求助:无库实现特定字符替换需求

Hey there! Let's break down why your code isn't working and fix it properly. I'll walk through the issues and give you both a corrected version and a more elegant optimized solution.

First, the Problems in Your Code

  1. Syntax Error in the let Block
    You've jammed all your repl patterns together on one line, which Haskell doesn't accept. Multiple function clauses in a let (or where) block need to be separated by newlines (or semicolons, but newlines are cleaner).

  2. Non-Exhaustive Pattern Matching
    Your repl function only handles '/' and digits 2-9. It completely ignores '1' and other characters like the 'w' in your example. When Haskell hits an unrecognized character, it'll throw a runtime error for non-exhaustive patterns.

  3. Using map Instead of concatMap
    Your repl function returns a String (a list of chars), but map repl x will give you a list of strings ([String]), not a single merged string. You need to concatenate those results into one final string.

Fixed Version (Direct Correction)

Here's your code adjusted to fix all the above issues:

replace :: String -> String
replace x = let
    repl '/' = replicate 10 '1'  -- Use replicate to avoid typing 10 '1's manually
    repl '9' = replicate 9 '1'
    repl '8' = replicate 8 '1'
    repl '7' = replicate 7 '1'
    repl '6' = replicate 6 '1'
    repl '5' = replicate 5 '1'
    repl '4' = replicate 4 '1'
    repl '3' = replicate 3 '1'
    repl '2' = replicate 2 '1'
    repl '1' = "1"  -- Keep '1' as-is
    repl c = [c]    -- Preserve any other character (like 'w')
  in concatMap repl x  -- concatMap merges all the returned strings into one

Optimized Version (Cleaner, Less Repetition)

Instead of writing a separate clause for every digit, we can convert the character to its numeric value and generate the right number of '1's automatically. This avoids repetitive code:

replace :: String -> String
replace = concatMap repl
  where
    repl '/' = replicate 10 '1'
    repl c
      | c `elem` ['2'..'9'] = replicate (read [c] :: Int) '1'
      | otherwise = [c]  -- Handles '1' and all non-target characters

How This Works

  • concatMap applies repl to each character in the input string, then concatenates all the resulting small strings into one final output.
  • replicate n '1' creates a string of n copies of '1'—way cleaner than typing out multiple '1's manually.
  • The guard clause checks if the character is a digit from 2-9, converts it to an integer with read [c], then uses that number to generate the correct number of '1's.
  • The otherwise case ensures every other character (including '1' and 'w') is kept exactly as it is.

Testing this with your example string "w1w1w8/w7w1w1//w" will give you the expected result: "w1w1w11111111/w1111111w1w1/1111111111/w" (with 8 '1's for '8', 10 '1's for each '/', 7 '1's for '7', etc.).

内容的提问来源于stack exchange,提问作者Marco Michaelis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:24:10