App(..., Ident seq, CompExpr(...))
みたいな感じにパースされることが分かった
x y z
を足して7になるリストを求めたいとのことで書いたのですが、ブレイス
さんの回答をみて、これはモナドでは?と思い、書いてみました!多分これでいいと思うのですが、合計で7になるのが取り出せません。なにか良いアイディアあればお願いします。またモナドの勉強を始めたばかりなので間違ってたらご指摘してもらえると嬉しいです(^_^)/module Test_ListMonad =
type ListBuilder () =
member this.Bind (m, f) = m |> List.collect f
member this.Return x = [x]
member this.ReturnFrom x = x
let lb = ListBuilder()
let lessThan n = [1..n]
let plusMinus a b c = [a, b, c]
let allPMs l m n = lb {
let! x = lessThan l
let! y = lessThan m
let! z = lessThan n
return! plusMinus x y z
}
allPMs 6 6 6 |> printfn "%A"
member this.Bind (x, f) =
let tplsum (a, b, c) = a + b + c
let idx = ( x |> List.collect f) |> List.map ( fun tpl -> tplsum tpl )
( idx, ( x |> List.collect f) )
||> List.zip
|> List.filter ( fun tpl -> fst tpl = 7 )
|> List.map ( fun elm -> snd elm )
let plusMinus a b c = [a; b; c]
にてリストにしたらシンプルになりました!delayとか使う方法はよくわからなかったです(汗)module Test_ListMonad =
type ListBuilder () =
member x.Bind (l, f) = l |> List.collect f
member x.ReturnFrom l =
match List.sum l with
| 7 -> [l] | _ -> []
let lb = new ListBuilder()
let lessThan n = [1..n]
let plusMinus a b c = [a; b; c] // <---ここが [a,b,c] tupleだったため扱いにくかった
let allPMs l m n = lb {
let! x = lessThan l
let! y = lessThan m
let! z = lessThan n
return! plusMinus x y z }
allPMs 6 6 6 |> printfn "%A"
module Test_ListMonad =
type ListBuilder () =
member x.Yield v = [v]
member x.Bind (l, f) = l |> List.collect f
let lb = new ListBuilder()
let listAll =
lb { let! x = [1..6]
let! y = [1..6]
let! z = [1..6]
yield [x;y;z]
|> fun l -> match List.sum l with 7 -> l | _ -> []
}
|> List.filter ( fun l -> l <> [] ) // ここがちょっと泥臭い気が、、、
|> printfn "%A"
open FSharpPlus
let listAll =
monadPlus {
let! x = [1..6]
let! y = [1..(7 - x)]
let! z = [1..(7 - x - y)]
if x + y + z = 7 then
return (x, y, z)
}
[<EntryPoint>]
let main argv =
printfn "%A" listAll
0