スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#入門中級編第2回(Computation Expression(2))

今回のお題は「Computation Expression(2)」です。
 
まずは宿題の解答から
type SyntacticTransformer1Builder() =
    member this.Bind (x,rest) =
        rest x
    
    member this.Return(x) =
        x
   
let ts1 = new SyntacticTransformer1Builder() 
 
let MulOfPlusOne m n =
    ts1 { let! u = m + 1
          let! v = n + 1
          return (u * v)}
          
においてMulOfPlusOneがどう解釈されるか、ts1.Bindとts1.Returnを使った通常のコードに直してください。上の方の例の******************************の間のような形です。
 
(解答例)
let MulOfPlusOne m n =
    ts1.Bind(m+1,(fun u ->
                    ts1.Bind(n+1,fun v ->
                         ts1.Return(u * v))))
 
さて今回は問題から。
問題
次の実行結果は?
 
type Ex00Builder() =
    member this.Bind (x,rest) =
        rest ((float) x)
        
    member this.Return x =
        x
 
let ex00 = new Ex00Builder()
 
let backResult  =
    ex00 { let! a = 2       //#1
           let sum = a + 3  //#2
           return sum }
 
答え,
エラーが出て、コンパイルできません。
this.Bindの定義より、右辺の2はfloat型に変換され、#2以下をaという鍵穴を付けたマトリョーシカで包んだものに押し込まれますので,aの型はfloat型となります。よって#2の部分で、float型とint型は足せないというエラーが出ます。
次のように直すと動きます。
let backResult  =
    ex00 { let! a = 2
           let sum = a + 3.0 //3を3.0に直した
           return sum }

type Ex00Builder =
  class
    new : unit -> Ex00Builder
    member Bind : x:int * rest:(float -> 'b) -> 'b
    member Return : x:'a -> 'a
  end
val ex00 : Ex00Builder
val backResult : float = 5.0           
           
 
ここで問題です。下のコードでResult0とResult1はそれぞれ何と評価されるでしょうか。
 
type Ex01Builder(f:float*float->float) =
    member this.Bind (x,rest) =
        rest (f x)
        
    member this.Return x =
        x
 
let bld0 = new Ex01Builder(fun (x,y) -> x*y)
let bld1 = new Ex01Builder(fun (x,y) -> x*y/2.0) 
 
let result0  =
    bld0 { let! a = (2.0,3.0)      
           let! b = (5.0,8.0)
           return a+b }
 
let result1  =
    bld1 { let! a = (2.0,3.0)      
           let! b = (5.0,8.0)
           return a+b }
 
答え、bld0では、let!において、右辺のタプルの成分を掛け合わせたものが左辺の識別子の値となり、bld1では、let!において、右辺のタプルの成分を掛け合わせたものを2.0で割ったものがが左辺の識別子の値となりますので、result0は46.0、result1は23.0と評価されます。
 
ということで今回は「let!の右辺と左辺ではmember.Bindの定義しだいでは、型が違うこともあるよ(違う方が普通なような気もしますが)」という例でした。
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。