
Hello, using the Text.Json library (and I'm reading I should be using Aeson instead... I'll migrate to it later), I'm a bit frustrated. At one point I'm getting a JSValue object, which could be anything, including a JSObject. But in this case I know I'm looking at a JSObject. I don't mind if Haskell crashes if that's not the case (for now), either it's a JSObject or the JSON I'm parsing is invalid. I hoped to do that conversion using pattern matching by giving non-exhaustive pattern match, considering only cases where the JSValue is in fact a JSONObject but somehow I can't make it... getObject :: JSValue -> JSObject JSValue getObject x@(JSObject _) = x --> doesn't compile the function returns a JSValue, I somehow wanted to point out to the compiler that if it gets there it's in fact a JSObject. getObject :: JSValue -> JSObject JSValue getObject (JSObject x) = JSObject x -> same as with the other attempt.. the compiler is saying the function is returning a JSValue: Couldn't match expected type `JSObject JSValue' with actual type `JSValue' In the return type of a call of `JSObject' In the expression: JSObject x In an equation for `getObject': getObject (JSObject x) = JSObject x I think I'm missing an obvious pattern in Haskell here, probably something I've already used elsewhere too, but somehow I don't make it. Otherwise answers saying that if I need to make such a "cast" then I'm using that library the wrong way are welcome (together to maybe a link to a tutorial explaining it the right way), but by curiosity I would still be interested in how to actually do that "cast" in this case. Thank you! Emmanuel

Hi Emmanuel. It's somewhat confusing that in Haskell, data constructors and datatypes can have the same name. They're nevertheless different beasts. A data constructor is a way to construct values of a datatype, or to destruct them via pattern matching. Such constructors themselves are *not* types. The definition of JSValue looks as follows:
data JSValue = JSNull | JSBool !Bool | JSRational Bool{-as Float?-} !Rational | JSString JSString | JSArray [JSValue] | JSObject (JSObject JSValue) deriving (Show, Read, Eq, Ord, Typeable)
So there are six different ways to construct a JSValue, the last one is the JSObject constructor. It contains one item which is of *type* JSObject JSValue. This time, JSObject refers to a datatype, also defined in the library:
newtype JSObject e = JSONObject { fromJSObject :: [(String, e)] } deriving (Eq, Ord, Show, Read, Typeable )
Now to your functions: if you write
getObject :: JSValue -> JSObject JSValue getObject x@(JSObject _) = x
or
getObject :: JSValue -> JSObject JSValue getObject (JSObject x) = JSObject x
you are writing essentially the identity function, but trying to assign a more specific type to the value. This doesn't quite work in Haskell. There's no subtyping between different datatypes. Instead, what you should do is perform the pattern match once and extract its contents:
getObject :: JSValue -> JSObject JSValue getObject (JSObject x) = x
Now you have the stuff that was "inside" the constructor, and isolated the point of failure. Cheers, Andres -- Andres Löh, Haskell Consultant Well-Typed LLP, http://www.well-typed.com

Thank you.
To be honest I'll have to return to this point later to properly "digest"
it because I don't complely get it yet.
It seems a bit crazy to me to give to the data JSObject the same name as
with the newtype JSObject. It is very confusing for me. But I'll get it, it
must just sink in.
Thanks a lot, because I would never understand that one on my own...
Emmanuel
On Thu, Oct 25, 2012 at 12:15 AM, Andres Löh
Hi Emmanuel.
It's somewhat confusing that in Haskell, data constructors and datatypes can have the same name. They're nevertheless different beasts. A data constructor is a way to construct values of a datatype, or to destruct them via pattern matching. Such constructors themselves are *not* types.
The definition of JSValue looks as follows:
data JSValue = JSNull | JSBool !Bool | JSRational Bool{-as Float?-} !Rational | JSString JSString | JSArray [JSValue] | JSObject (JSObject JSValue) deriving (Show, Read, Eq, Ord, Typeable)
So there are six different ways to construct a JSValue, the last one is the JSObject constructor. It contains one item which is of *type* JSObject JSValue. This time, JSObject refers to a datatype, also defined in the library:
newtype JSObject e = JSONObject { fromJSObject :: [(String, e)] } deriving (Eq, Ord, Show, Read, Typeable )
Now to your functions: if you write
getObject :: JSValue -> JSObject JSValue getObject x@(JSObject _) = x
or
getObject :: JSValue -> JSObject JSValue getObject (JSObject x) = JSObject x
you are writing essentially the identity function, but trying to assign a more specific type to the value. This doesn't quite work in Haskell. There's no subtyping between different datatypes.
Instead, what you should do is perform the pattern match once and extract its contents:
getObject :: JSValue -> JSObject JSValue getObject (JSObject x) = x
Now you have the stuff that was "inside" the constructor, and isolated the point of failure.
Cheers, Andres
-- Andres Löh, Haskell Consultant Well-Typed LLP, http://www.well-typed.com

Andres Löh
Hi Emmanuel.
It's somewhat confusing that in Haskell, data constructors and datatypes can have the same name. They're nevertheless different beasts. A data constructor is a way to construct values of a datatype, or to destruct them via pattern matching. Such constructors themselves are *not* types.
The definition of JSValue looks as follows:
data JSValue = JSNull | JSBool !Bool | JSRational Bool{-as Float?-} !Rational | JSString JSString | JSArray [JSValue] | JSObject (JSObject JSValue) deriving (Show, Read, Eq, Ord, Typeable)
So there are six different ways to construct a JSValue, the last one is the JSObject constructor. It contains one item which is of *type* JSObject JSValue. This time, JSObject refers to a datatype, also defined in the library:
newtype JSObject e = JSONObject { fromJSObject :: [(String, e)] } deriving (Eq, Ord, Show, Read, Typeable )
Now to your functions: if you write
getObject :: JSValue -> JSObject JSValue getObject x@(JSObject _) = x
or
getObject :: JSValue -> JSObject JSValue getObject (JSObject x) = JSObject x
you are writing essentially the identity function, but trying to assign a more specific type to the value. This doesn't quite work in Haskell. There's no subtyping between different datatypes.
Instead, what you should do is perform the pattern match once and extract its contents:
getObject :: JSValue -> JSObject JSValue getObject (JSObject x) = x
Now you have the stuff that was "inside" the constructor, and isolated the point of failure.
Cheers, Andres
I'm sorry, but I copied exact code and I'm still getting an error: $:l tst.hs [1 of 1] Compiling Main ( tst.hs, interpreted ) Ok, modules loaded: Main. $let a = toJSObject [("A","a")] $a JSONObject {fromJSObject = [("A","a")]} $encode a "{\"A\":\"a\"}" $getJSObj a <interactive>:428:10: Couldn't match expected type `JSValue' with actual type `JSObject [Char]' In the first argument of `getJSObj', namely `a' In the expression: getJSObj a In an equation for `it': it = getJSObj a $

Hi Jamie,
I'm sorry, but I copied exact code and I'm still getting an error:
$:l tst.hs [1 of 1] Compiling Main ( tst.hs, interpreted ) Ok, modules loaded: Main. $let a = toJSObject [("A","a")] $a JSONObject {fromJSObject = [("A","a")]} $encode a "{\"A\":\"a\"}" $getJSObj a
<interactive>:428:10: Couldn't match expected type `JSValue' with actual type `JSObject [Char]' In the first argument of `getJSObj', namely `a' In the expression: getJSObj a In an equation for `it': it = getJSObj a $
'getJSObj' seems to extract a JSObject from a JSValue, but you are giving a JSObject to 'getJSObj'. Try this: getJSObj $ JSValue a Greetings, Daniel

Daniel Trstenjak
Try this:
getJSObj $ JSValue a
Greetings, Daniel
Ahh. I got confused since (JSObject JSValue) is one of the JSValue types. Where is the JSValue constructor? I saw it in Text.JSON.Types, but even after importing it, I get: <interactive>:492:6: Not in scope: data constructor `JSValue'

Hi Jamie,
Ahh. I got confused since (JSObject JSValue) is one of the JSValue types. Where is the JSValue constructor? I saw it in Text.JSON.Types, but even after importing it, I get:
Ups, sorry, the data constructor to get a JSValue from a JSObject is named - well - also JSObject. So it's: getJSObj $ JSObject a There's a data type named JSObject: newtype JSObject e = JSONObject { fromJSObject :: [(String, e)] } deriving (Eq, Ord, Show, Read, Typeable ) And there's a data constructor with the name JSObject for the data type JSValue: data JSValue = ... | JSObject (JSObject JSValue) deriving (Show, Read, Eq, Ord, Typeable) Greetings, Daniel

Daniel Trstenjak
Ups, sorry, the data constructor to get a JSValue from a JSObject is named - well - also JSObject.
So it's:
getJSObj $ JSObject a
There's a data type named JSObject:
newtype JSObject e = JSONObject { fromJSObject :: [(String, e)] } deriving (Eq, Ord, Show, Read, Typeable )
And there's a data constructor with the name JSObject for the data type JSValue:
data JSValue = ... | JSObject (JSObject JSValue) deriving (Show, Read, Eq, Ord, Typeable)
Greetings, Daniel
Thanks. I'd seen that mentioned above, but I'm a bit new to Haskell and didn't really understand what that meant. In fact, I still don't. Do you have any good resources on that? None of the tutorials/manuals were entirely clear to me, nor was the wiki(http://www.haskell.org/haskellwiki/Constructor), which uses the same statement as the example of both type and data constructors.

There are types and constructors. If "int i = 2"; is a statement, int
is the type, and 2 is the constructor. You can't put 2 on the left
side and you can't put int on the right side, it wouldn't work. The
way I like to think of it is that there are types, and then there are
values. Each value has a type. Each type can be represented by
different values. Types are used for type info and values that are
used for code. When you are declaring a data type it could be
composed of both pieces, and sometimes they are named the same, which
is where your confusion comes from.
data blahtype = blah | blah2 | blah3 int | blah4 Char Int | blahtype
The first blahtype is the type, the others are constructors. That
last blahtype is a constructor, not a type. It is completely legal to
have the same name as its type. The char and int are of course types.
fooFunc :: JSObject -> JSValue -> IO JSValue -- <- all these are types
fooFunc (JSONObject blah) (JSBool bvalue) = return $ JSObject
(JSONObject JSNull) -- <- all these are value related
It is very easy to see when writing functions, but when writing data
types it takes a bit of getting used to because it requires both
aspects at the same time.
data JSValue = ... | JSObject (JSObject JSValue) | ...
The first JSValue is a type. The first JSObject is a constructor.
The second JSObject is a type and so is the second JSValue. Put them
together it is a single type "JSObject JSValue". So that JObject
constructor takes a single type of (JSObject JSValue).
newtype JSObject e = JSONObject [(String, e)]
The first JSObject is again a type. The e will be replaced with a
type. JSONObject is a constructor again. The arguments to JSONObject
are types (String, and whatever e is). Constructors are essentially
the first word in each possible value. They are used to pattern match
and to construct new values.
I realize it looks confusing, but it becomes second nature after a little while.
On Thu, Mar 28, 2013 at 3:22 PM, Jamie F Olson
Daniel Trstenjak
writes: Ups, sorry, the data constructor to get a JSValue from a JSObject is named - well - also JSObject.
So it's:
getJSObj $ JSObject a
There's a data type named JSObject:
newtype JSObject e = JSONObject { fromJSObject :: [(String, e)] } deriving (Eq, Ord, Show, Read, Typeable )
And there's a data constructor with the name JSObject for the data type JSValue:
data JSValue = ... | JSObject (JSObject JSValue) deriving (Show, Read, Eq, Ord, Typeable)
Greetings, Daniel
Thanks. I'd seen that mentioned above, but I'm a bit new to Haskell and didn't really understand what that meant. In fact, I still don't. Do you have any good resources on that? None of the tutorials/manuals were entirely clear to me, nor was the wiki(http://www.haskell.org/haskellwiki/Constructor), which uses the same statement as the example of both type and data constructors.
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

David McBride
data JSValue = ... | JSObject (JSObject JSValue) | ...
The first JSValue is a type. The first JSObject is a constructor. The second JSObject is a type and so is the second JSValue. Put them together it is a single type "JSObject JSValue". So that JObject constructor takes a single type of (JSObject JSValue).
newtype JSObject e = JSONObject [(String, e)]
The first JSObject is again a type. The e will be replaced with a type. JSONObject is a constructor again. ...
Thank you very much for the clarification! This is what I couldn't wrap my head around. JSObject as a data constructor creates objects of type JSValue, not JSObject, which are instead created by JSONObject. Frankly, it's the Text.JSON api that's confusing more than the language. The language feature is more or less like classes vs constructors in OOP (except for types not actually existing in Haskell) The other weird thing is that the types don't exist as objects that can be referenced.

On Fri, Mar 29, 2013 at 2:22 AM, Jamie F Olson
None of the tutorials/manuals were entirely clear to me, nor was the wiki(http://www.haskell.org/haskellwiki/Constructor), which uses the same statement as the example of both type and data constructors.
Indeed, it's a very common gotcha: JSObject is a type constructor in the sense that it takes a type and returns a type. It so happens that JSObject is also a data constructor that takes a value and returns another value of the datatype of which it is a constructor. Why is this ambiguity allowed? Because JSObject as type constructor can't be used at the term level. You can only write type signatures with it, you can't use it in an expression. JSObject as data constructor is the reverse. It's a function like any other. In this case, it has type signature JSObject :: JSObject JSValue -> JSValue. Note how JSObject after the double colon is JSObject as the one-parameter type constructor (see newtype definition). Confusing, eh? After a bit of practice, it should be clear that this is a means of conserving the namespace. You can always start with a different naming convention on your own code until you get used to the separation between types and terms (which does tend to become muddled as dependent types loom, but that's a story for later). -- Kim-Ee

David McBride
data JSValue = ... | JSObject (JSObject JSValue) | ...
Thank you! I think the two strange things as an outsider particularly from more OO languages are that types aren't objects, and then the strangeness of the naming convention. Would it have been legal to define data JSValue as something like this instead? data JSValue = JSValue | JSValue !Bool | JSValue !Rational | JSValue JSString | JSValue [JSValue] | JSValue (JSObject JSValue)

On Thu, Mar 28, 2013 at 6:34 PM, Jamie F Olson
Would it have been legal to define data JSValue as something like this instead?
data JSValue = JSValue | JSValue !Bool | JSValue !Rational | JSValue JSString | JSValue [JSValue] | JSValue (JSObject JSValue)
No; the data constructor used tells it what to expect afterward. -- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

Hi Jamie, On Thu, Mar 28, 2013 at 10:34:26PM +0000, Jamie F Olson wrote:
Thank you! I think the two strange things as an outsider particularly from more OO languages are that types aren't objects, and then the strangeness of the naming convention.
In C++ you could have something like:
class JSObject {
public:
typedef std::map
participants (7)
-
Andres Löh
-
Brandon Allbery
-
Daniel Trstenjak
-
David McBride
-
Emmanuel Touzery
-
Jamie F Olson
-
Kim-Ee Yeoh