2016-04-10 20 views
2

Elm内の変数の型をチェックする関数は存在しますか?例えば(REPL):Elm - 値の型のチェック

numberTwo = 2 
..... 
returnType numberTwo 
"number" : String 

このための動機はあなたがSignal.map[n]を使用しているときの状況は通常、信号であることではないすべての引数に適用される関数に生じることである - 彼らはその後、通常 "でなければなりません信号をを使って昇格させました。そのような引数のタイプを確認できたら、そのような引数を自動的に信号に変換する関数Signal.allSigMap[n]を作成することができました。

ので

Signal.map2 grandFatherClock clockSignalElement (Signal.constant cabinetElement) 

Signal.allSigMap2 grandFatherClock clockSignalElement cabinetElement 

はしかし悪い習慣だろうになります。私にお知らせください。

+0

変数のタイプをチェックする理由を説明できますか?このような関数をどのように使用するのかを示すかもしれません。 – ianmjones

+0

確かに更新された質問。 – category

答えて

10

まずを使用して、Signalに必要なタイプを宣伝する方法としてお答えします。その場合には、returnTypeやその他の関数が実際にはStringではなく型を返します。これは、型チェッカーを幸せにする方法がないためです。

このような機能は存在せず、今日のエルム内には存在しません。あなたが求めているのは、コンパイル時に値の型を調べ、その型で関数を実行できるものです。

これがElmに現在存在するものと根本的に異なる理由を確認するには、そのような関数が存在すると仮定しましょう。

returnType : a -> ? 

正確にタイプがreturnTypeであるという最初の質問に直面しています。これを伝えて、Typeというタイプのタイプがあるとしましょう(それには、それ以外の論理的な問題はありません)。

returnType : a -> Type 

実際にこの機能をどのように使用しますか?おそらく型を返すので、型シグネチャに入る可能性があります。

x : returnType 5 

はエルムで他のすべてとは全く異なるタイプの署名であること。数値リテラル(と関数)があります!突然あなたはこのようなことを書くことができます。

y = 5 

x : returnType y 
x = 6 

これは、エルムのタイプシステムができることを超えています。そのような(エキサイティングでパワフルな)タイプのレベルと値のレベルの混合は、dependent typingとして知られており、主流の完全に依存する型付き言語は存在しません。主流に最も近いものは、おそらくCoq、Agda、Idris、およびATSであり、それらはすべてかなり不明瞭です。

文字のように、値の型を表す文字列を表示する関数returnType : a -> Stringがありますが、これは他の理由でもElmでは不可能です。このような関数(実行時にアプリケーションが発生する)は、実行時の値に関する型情報を再構築できなければなりませんが、Elmの実行時の値は単なるJavascript値です。彼らは彼らのエルムのタイプを取り除いた。 Javascript値から元のElm型を再構成するか(異なる型が同じJavascript値になる可能性は常にありません)、または特別なコンパイラのサポートが必要です。

Elm REPLの場合、後者が選択されます。 REPL全体はHaskellで書かれており、Elmの型がHaskellランタイムでどのように実装されているかを利用しています。

+3

過小評価 –

1

コアライブラリにはこのような機能はありません。あなた自身で作成する必要があります。これは半完成です。これは、elm-replをリバースエンジニアリングできるためです。

+0

私が誤解していないなら、elm-replはHaskelで実装されていますが、実際はElmでは実装されていません。 – konung

1

は、私はまた、エルムでTYPEOF理由なしINSTANCEOFまたはを疑問に思いました。その後、FRPの深い理解のために徹底的に文書を調べました。常にデータの形を知っておく必要があります。 Elms Tagged Unionsのパターンを使用するには、既知のタイプをフィルタリングして、希望の値にアクセスできる必要があります。注意してください。case of ...のすべての枝は同じ型でなければなりませんが、あなたが望む型にアクセスできるようにダミーのセンチネル値を持つすべての既知の型のスーパーセットを持つタプルを使用することを排除するものではありません。

図については以下を参照コード:

仮定:

1.Yourが使用

2.Usingセンチネルが

import Html exposing (text) 



    type Input = Nothing | ILetter String | INumber Int | IFloat Float 

inputs: List (Input) 
inputs = [ Nothing, IFloat 8.34, ILetter "A", INumber 5, INumber -1, IFloat -12.0, ILetter "123!"] 


-- 
doSomething: Input -> (String, Int, Float) 
doSomething myInput = 
    case myInput of 
    Nothing -> 
     ("not here!", -69, 69.0) 

    ILetter string -> 
      if string /= "DarnString" then 
      (string, 0, 0) 
      else 
      ("DarnString", -1, -1.0) 

    INumber int -> 
      if int > 0 then 
      ("GoodInt" , int, toFloat int)  
      else 
      ("DarnInt" , int, toFloat int) 

    IFloat float -> 
      if float < 0 then 
      ("Goodfloat", truncate float, float) 
      else 
      ("Darnfloat", truncate float, float) 




-- I am only interested in using strings 
myStringFilter (mString, mInt, mFloat) = 
      if mString == "DarnString" || mString == "Darnfloat" || mFloat < 0 || mString == "DarnInt" || mInt > 0 then 
       "We are not the String(s) you were looking for!" 
      else 
       mString 

myFloatFilter (mString, mInt, mFloat) = 
      if mString == "DarnString" || mString == "Darnfloat" || mString == "DarnInt" then 
       696969696.696969696969 
      else     
       mFloat 

myIntFilter (mString, mInt, mFloat) = 
      if mString == "DarnString" || mString == "Darnfloat" || mString == "DarnInt" then 
       -696969696 
      else     
       mInt    

main = 
    text (toString <| List.map myStringFilter (List.map doSomething inputs)) 
    --text <| myStringFilter <| doSomething (IFloat 14.83) 
    -- text <| toString <| myFloatFilter <| doSomething (IFloat -14.83) 
    --text <| toString <| myIntFilter <| doSomething (INumber 5) 
2
値ときに型がタグ付けされ、所望の

Thiタイプ消去(https://en.wikipedia.org/wiki/Type_erasure)のために可能ではありません。 elmのすべての型を整える必要があるため、コンパイラはすべての型がコンパイル時に並んでいることを確認できます。これが完了すると、実際に実行されるコンパイル済みコードからすべての型情報を安全に削除できます。これは実際にコードをより効率的にするため、実行時にすべての値で型情報(または典型的なjavascriptコードで慣れ親しんでいるような実行時型チェック)を持ち歩かなくてはならないためです。

elmのような言語にランタイム型のイントロスペクションが追加される可能性は低いと思います。実行時に型をチェックする必要があるのは、あまり設計されていないコードのコードマレットです。