functional-programming - 如何在 Ocaml 中编写模式匹配以便易于扩展?

标签 functional-programming ocaml

我在学习 Jason Hickey's Introduction to Objective Caml .
有一个这样的练习:

Exercise 4.3 Suppose we have a crypto-system based on the following substitution cipher, where each plain letter is encrypted according to the following table.

Plain     | A B C D
--------------------
Encrypted | C A D B

For example, the string BAD would be encrypted as ACB.

Write a function check that, given a plaintext string s1 and a ciphertext string s2, returns true if, and only if, s2 is the ciphertext for s1. Your function should raise an exception if s1 is not a plaintext string. You may wish to refer to the string operations on page 8. How does your code scale as the alphabet gets larger? [emphasis added]



基本上,我用 might-be-stupid-naive 写了两个函数这个练习的方法。
我想先征求一下我的解决方案的建议。
然后我想就练习中突出显示的缩放解决方案寻求提示。

使用 if else
let check_cipher_1 s1 s2 = 
    let len1 = String.length s1 in
        let len2 = String.length s2 in              
            if len1 = len2 then
                    let rec check pos =
                        if pos = -1 then
                            true
                        else
                            let sub1 = s1.[pos] in
                                let sub2 = s2.[pos] in
                                    match sub1 with
                                        | 'A' -> (match sub2 with
                                                    |'C' -> check (pos-1)
                                                    | _ -> false)
                                        | 'B' -> (match sub2 with
                                                    |'A' -> check (pos-1)
                                                    | _ -> false)
                                        | 'C' -> (match sub2 with
                                                    |'D' -> check (pos-1)
                                                    | _ -> false)
                                        | 'D' -> (match sub2 with
                                                    |'B' -> check (pos-1)
                                                    | _ -> false)
                                        | _ -> false;
                                            in
                                                check (len1-1)
            else
                false
到处使用纯匹配
let check_cipher_2 s1 s2 = 
    let len1 = String.length s1 in
        let len2 = String.length s2 in
            match () with
                | () when len1 = len2 -> 
                        let rec check pos =
                            match pos with
                                | -1 -> true
                                | _ -> 
                                    let sub1 = s1.[pos] in
                                        let sub2 = s2.[pos] in
                                            (*http://stackoverflow.com/questions/257605/ocaml-match-expression-inside-another-one*)
                                            match sub1 with
                                                | 'A' -> (match sub2 with
                                                            |'C' -> check (pos-1)
                                                            | _ -> false)
                                                | 'B' -> (match sub2 with
                                                            |'A' -> check (pos-1)
                                                            | _ -> false)
                                                | 'C' -> (match sub2 with
                                                            |'D' -> check (pos-1)
                                                            | _ -> false)
                                                | 'D' -> (match sub2 with
                                                            |'B' -> check (pos-1)
                                                            | _ -> false)
                                                | _ -> false
                                                    in
                                                        check (len1-1)
                | () -> false
好的。以上两种解决方案类似。
我制作了这两个,因为在这里http://www.quora.com/OCaml/What-is-the-syntax-for-nested-IF-statements-in-OCaml ,有人说if else不是首选。
这基本上是我第一次写 not-that-simple在我的一生中发挥作用。所以我真的很想得到建议 这里。
例如,
  • 我该如何改进这些解决方案?
  • 我应该更喜欢 matchif else ?
  • 我在设计 recuse the rec正确吗?
  • 如果那 in check (len1-1)正确的?

  • 缩放它
    练习问How does your code scale as the alphabet gets larger? .我现在真的没有线索。在 Java 中,我会说我会有一个 map ,然后对于 s1 中的每个字符, 我在找 s2对于相应的字符并查看它是否是 map 中的值。
    对此有何建议?

    最佳答案

    这是一个简单的解决方案:

    让 tr = 函数
    | 'A' -> 'C'
    | 'B' -> 'A'
    | 'C' -> 'D'
    | 'D' -> 'B'
    | _ -> 失败“不是明文”

    让检查 ~tr s1 s2 = (String.map tr s1) = s2

    检查 ~tr "坏""ACD"

    您可以通过使用 tr 组合来添加更多字母。 IE。

    让 comp c1 c2 x = try (c1 x) with _ -> (c2 x)
    让 tr2 = comp tr(函数 | 'X' -> 'Y')

    关于functional-programming - 如何在 Ocaml 中编写模式匹配以便易于扩展?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14343379/

    相关文章:

    algorithm - clojure 中的链式调用?

    .net - 功能范式的效率

    scala - kind-projector 返回奇怪的结果

    unix - 如何在 OCaml 中使用 Unix.create_process 真正创建一个进程?

    c++ - 我的编译器在 C/C++、OCaml 和 F# 之间犹豫不决

    scala - 如何证明两种类型的等价性以及签名是单一存在的?

    haskell - 如何在代码中调用函数来返回多项式的次数?

    ocaml - 可选择将额外数据附加到类型

    pattern-matching - 模式匹配中的 OCaml 多态变体

    ocaml - 如何将模块映射到 OCaml 中的模块类型?