2016-04-07 10 views
1

私は最後に、elmと男の子との機能プログラミングの優れたエントリーポイントを見つけました。私はそれが好きですか?まだいくつかの概念に関する基本的な優雅さはまだありません。地図を移動しました

次のようなコードを書いていることがよくありますが、これはすべきことをしているようですが、より経験豊富な人がよりコンパクトで直接的なアプローチを提案できる場合は、これについていくつかの貴重な洞察を与えることができますそれで(u)rcery。

私はこれがに煮詰めることができ想像何、以下 のようなもの(<->はベクトル減算演算子である)である:

edgeDirections : List Vector -> List Vector 
edgeDirections corners = List.map2 (\p v -> p <-> v) corners (shiftr 1 corners) 

が、私は本当にだろう方法に満足のいくアプローチを持っていませんshiftrを実行します。

しかし、stackoverflowのルールはそれを要求します、ここで私が試みたものです。私は(私は絶対Debug.crashを嫌い、私はMaybe程度満足していない)shiftrのための可能な使用法の醜い例を書いた:

ベクトルのリスト(ポリゴンのコーナーポイント)が与えられ、によって方向ベクトルを計算しますリスト内の最初のエントリと最後のエントリの差分から始めて、各コーナーベクトルと前のものとの差を計算する。

[v1,v2,v3] -> [v1-v3,v2-v1,v3-v2]

はここに行く:

edgeDir : Vector -> (Maybe Vector, List Vector) -> (Maybe Vector, List Vector) 
edgeDir p (v, list) = 
    case v of 
    Nothing -> 
     Debug.crash ("nono") 

    Just vector -> 
     (Just p, list ++ [ p <-> vector ]) 


edgeDirections : List Vector -> List Vector 
edgeDirections corners = 
    let 
    last = 
     List.head <| List.reverse corners 
    in 
    snd <| List.foldl edgeDir (last, []) corners 


main = 
    show <| edgeDirections [ Vector -1 0, Vector 0 1, Vector 1 0 ] 

私はまだ私は知りません。この結果は、おそらく既存の言語構造を使用して、より直接的な方法で達成することができる方法に任意の洞察力に感謝し、または任意のMaybeで痛みを和らげる方法の指針。後者はJustが可能ではありませんが、私は前にa)私を吹き飛ばし、b)私の頭を数回傷つけるようにしていると確信しています:)

ありがとう、

答えて

2

Elmにinit and lastの機能が組み込まれていれば、これはもっときれいかもしれません。

パターンマッチングを行うことで、すべてのメイベズから離れていくことができます。ここではちょうどパターンマッチングとアキュムレータを使用して私の試みです。

import List exposing (map2, append, reverse) 

shiftr list = 
    let shiftr' acc rest = 
    case rest of 
     [] -> [] 
     [x] -> x :: reverse acc 
     (x::xs) -> shiftr' (x::acc) xs 
    in shiftr' [] list 

edgeDirections vectors = 
    map2 (<->) vectors <| shiftr vectors 

(\p v -> p <-> v)と同等であるにも注意(<->)のマッピング関数の短縮書き込み、。

と仮定エルムinitlast機能を持っていなかった - ちょうどすぐにここでそれらを定義してみましょう:

init list = 
    case list of 
    [] -> Nothing 
    [_] -> Just [] 
    (x::xs) -> Maybe.map ((::) x) <| init xs 

last list = 
    case list of 
    [] -> Nothing 
    [x] -> Just x 
    (_::xs) -> last xs 

を次に、あなたのshiftr機能のようなものに短縮することができます

shiftr list = 
    case (init list, last list) of 
    (Just i, Just l) -> l :: i 
    _ -> list 
+0

これは正確です私が以前に見てきたパターンは、ここで適用できると思っていました。デモをありがとう!奇妙なことに、 '(x :: xs)'は、 'x'は' Nothing'ではないという意味ですか?編集:ストライク、私はそれがそれを意味しないと確信している、それはなぜこれが有利な、それを持っている理由です。 – mindandmedia

0

私が「ハングアップ」した直後、私はこれを思い付いたが、私はそれも正しいかどうこれはまだ大幅に、大幅に改善することができます確信している(と、それだけのために働くのn = 1)

shiftr : List a -> List a 
shiftr list = 
    let 
    rev = 
     List.reverse list 
    in 
    case List.head rev of 
     Nothing -> 
     list 

     Just t -> 
     [ t ] ++ (List.reverse <| List.drop 1 rev) 


main = 
    show (shiftr [ 1, 2, 3, 4 ] |> shiftr) 
関連する問題