tag:blogger.com,1999:blog-5569894.post4009470264898375864..comments2023-11-08T13:18:07.006+00:00Comments on Distributed Memory: An approximate type-based solution to the strings problemSteve Gilhamhttp://www.blogger.com/profile/03622573187942388226noreply@blogger.comBlogger1125tag:blogger.com,1999:blog-5569894.post-27147870375236507192011-12-15T01:45:57.134+00:002011-12-15T01:45:57.134+00:00I got to this from PlanetF# and decided to play wi...I got to this from PlanetF# and decided to play with it a little.<br /><br />I was able to get rid of the SafeStringBase and the # types by making the ILanguage interface generic, adding some type constraints to SafeString.<br /><br />Instead, the Xml type has to inherit from SafeString and has to define a constructor explicitly. However, I think this solution is a little close to Haskell type classes.<br /><br />Sorry I don't know how to paste it as code so will put it here just as plain text.<br /><br />#light<br /><br />open System<br /><br />module TypeStrings =<br /><br /> let rec foldr f z l =<br /> match l with<br /> | [] -> z<br /> | x::xs -> f x (foldr f z xs)<br /><br /> type ILanguage<'T when 'T :> ILanguage<'T>> =<br /> abstract member LiteralFragment : String -> 'T // String is a literal language fragment<br /> abstract member LiteralText : String -> 'T // String is literal text<br /> abstract member NativeRepresentation : 'T -> String // Gets the native-language representation<br /> abstract member Language : unit -> String // Gets the name of the language <br /> abstract member Empty : unit -> 'T // creates an empty SafeString in the Language<br /> abstract member Add : 'T -> 'T -> 'T<br /> <br /> type SafeString<'TLanguage when 'TLanguage :> ILanguage<'TLanguage> and 'TLanguage :> SafeString<'TLanguage> and 'TLanguage : (new : unit -> 'TLanguage) > (content: String) =<br /> static let language : 'TLanguage = new 'TLanguage()<br /> <br /> static member Empty : SafeString<'TLanguage> =<br /> language.Empty() :> SafeString<'TLanguage><br /> <br /> static member Fragment fragment =<br /> language.LiteralFragment fragment :> SafeString<'TLanguage><br /><br /> static member Text text =<br /> language.LiteralText text :> SafeString<'TLanguage><br /> <br /> static member Join (strings : seq<'TLanguage>) =<br /> let l = Seq.toList strings<br /> (foldr language.Add (language.Empty()) l) :> SafeString<'TLanguage><br /> <br /> static member Lang with get() = language<br /><br /> static member (+) ((self: SafeString<'TLanguage>), (other: SafeString<'TLanguage>)) : SafeString<'TLanguage> =<br /> // don't think you can get rid of the down cast here<br /> (language.Add (self :?> 'TLanguage) (other :?> 'TLanguage)) :> SafeString<'TLanguage><br /> <br /> member this.AsString with get() = content<br /> <br /> <br /> type Xml (content: String) =<br /> inherit SafeString(content)<br /><br /> // this is a required hack<br /> new () = Xml("")<br /> <br /> interface ILanguage with<br /> member self.LiteralFragment s = new Xml(s)<br /> member self.LiteralText s = new Xml(System.Security.SecurityElement.Escape(s))<br /> member self.NativeRepresentation s =<br /> s.AsString.Replace("&apos;", "'").<br /> Replace(""", "\"").Replace(">", ">").<br /> Replace("<", "<").Replace("&", "&")<br /> member self.Language () = "XML"<br /> member self.Empty () = new Xml(String.Empty)<br /> <br /> member self.Add x y = (new Xml(x.AsString + y.AsString)) <br /> <br /> []<br /> let main a =<br /> let frag = SafeString.Fragment "<em>wow!</em>"<br /> printfn "%s" frag.AsString<br /> let text = SafeString.Text "ham & eggs"<br /> printfn "%s" text.AsString<br /> <br /> let sum = frag + text<br /> printfn "%s" sum.AsString<br /> 0Davehttps://www.blogger.com/profile/08754613228118986505noreply@blogger.com