Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The downside of that approach though is that you end up wrapping the bulk of the API functions you're using to make them conformant. You've got a huge amount of extra work creating and maintaining these components, and a major training workload for any new hires so they know why they can't use the standard options they're used to and what the internal replacements are.

Personally, I'd rather go Hungarian.

Edit - well, yes, you may well be able to do this sort of thing nice and easily in Haskell, but I'm not sure that going with Haskell to avoid the training and maintenance overhead of complicating your Java (or whatever) is a net reduction in workload and hiring difficulty...



This is a Java/Python/etc problem, not a fundamental one. In Haskell, the wrapping process is merely an application of liftM:

    type UnsafeUserGenerated = UserGenerated a
    instance Monad UnsafeUserGenerated where
        ... (monadic boilerplate skipped)...

    apiFunction :: String -> String

    funcOfUnsafe :: U -> UnsafeString
    funcOfUnsafe unsafe = (liftM apiFunction) unsafe


Does it really have to be a monad? Isn't a functor what we're really looking for?


It depends; if all you want to do is lift normal functions to the domain of unsafe operation (where an unsafe input implies unsafe output), then sure:

    newtype Unsafe a = Unsafe a
    
    instance Functor Unsafe where
        fmap f (Unsafe k) = Unsafe . f $ k

    addTwo :: Int -> Int
    addTwo = (+2)

    unsafeAddTwo :: Unsafe Int -> Unsafe Int
    unsafeAddTwo = fmap addTwo
But really, I'm not sure this is the right approach. Even values generated inside my program need to be quoted for inclusion on an HTML page. What you want to avoid is double-quoting, so what you need is simpler:

    data Content = Quoted String | Unquoted String

    output :: [Content] -> Content
    output = concatMap f
       where f (Unquoted x) = quote x
             f (Quoted   x) = x
Now the type system ensures that (output . output) == output, which is what you really want to ensure. Tainted data, I think, is a separate concern. And the solution, in that case, doesn't involve a functor, it involves making sure your library tags everything as Unsafe and that your data validation functions remove that annotation:

    type Params a = Map String (Unsafe a) -- keys may also be unsafe, YMMV

    readHtmlForm :: Request -> Params String
    validateField :: Validatable a => Unsafe a -> a

    main = output . Unquoted . validateField . get "foo" . readHtmlForm <$> fakeHttpRequest


That comment illustrates the problem with Haskell. Yes it's nice and logical but for some reason also very hard.


This comment illustrates the problem with comments about problems with Haskell. It doesn't quite understand what it's complaining about.

Functor vs. Monad in this case is a way of talking about how exactly this construct should work --- it's not a meaningless distinction. As another response to my comment mentioned, both a functor or a monad are applicable. The question is whether two instances of this data type (I'm using non-Haskell-y terms for clarity) have influence on each other (in rough terms). So it's not that I was complaining that the parent was wrong. I was complaining that the semantics he was imposing on his quoted strings were too restrictive. Another poster instead mentioned ways in which mine were too loose. So my post was part of a constructive debate on what exactly we want quoted strings to do. That Haskell provides a vocabulary for communicating precisely and tersely is not it's fault, it is one of its strengths.


Any monad is also a functor, so they're both right!


Actually, he probably wants an applicative functor, which sits between functors and monads.

Or perhaps an arrow or a co-monad are better? ;o)


> [...] but for some reason also very hard.

Yes. But that's a feature, not a bug.


It's not hard, it's different.


The way I envisioned using it, yes. The use of a Monad over a Functor is merely because I'm still very much a Haskell newbie.


As siblings point out, how much work you have to do depends on your language and the available facilities. In Java, this might be a huge pain - Haskell, etc. less so. It's more likely that this is done as part of the framework or libraries generally - how many people are, to continue this example, writing their own web framework? In .NET for example, ASP.NET MVC includes an HtmlString class for similar purposes. Other languages can approach it in different ways. You may find as well that even with something like .NET, not the most expressive of type systems, you could still make life fairly easy by providing appropriate implicit type conversions in one direction.


In most languages that support this sort of things, can't you use SafeString in places where String is expected, as long as you declare SafeString as a sort of String?


I wouldn't want SafeString is-a String, I would want a conversion from SafeString to String that removes whatever encoding or escaping was applied. Otherwise you end up re-encoding values that unbeknownst to you don't need it, which is why there are thousands of terrible PHP bulletin boards out there which won't let you use quotes without mangling them.


In Java, String is a final class.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: