3

I really cannot figure out the syntax necessary for this, and it probably comes from my lack of understanding of how types work.

I want a type DataPoint, which stores either a tuple (x, dataval) or two fields x and dataval (where x is a Double and dataval is a Complex Double.

I want a Monad instance where it goes something like:

instance Monad (DataPoint x dataval) where
    return dataval = DataPoint 0.0 dataval
    DataPoint x dataval >>= f = DataPoint x (f dataval)

Basically, the "value" of the monad is dataval, and x is just a part of the container.

I don't think my syntax is correct though. If i define DataPoint as

data DataPoint x dataval = DataPoint { x       :: Double
                                     , dataval :: Complex Double }

then it should work, right?

Only I get a "kind mismatch"

The first argument of `Monad' should have kind `* -> *',
but `DataPoint x dataval' has kind `*'

Can anyone help me get the functionality/monad I am trying to acheive?

Justin L.
  • 13,510
  • 5
  • 48
  • 83
  • This datatype cannot be made a monad and it doesn't seem to make sense for it to be one either. What are you trying to accomplish here? – hammar Apr 29 '13 at 08:10
  • I'm trying to store "dataval", along with an x value associated with it. And then using `DataPoint >>= f` to apply `f` to `dataval`, and leave `x` unchanged. – Justin L. Apr 29 '13 at 08:11
  • That sounds more like a plain functor, except they have to support `dataval` being any type, not just `Complex Double`. It might make more sense to just define a `fmap`-like function for your type without involving type classes at all. – hammar Apr 29 '13 at 08:13
  • how would i go about implementing/instancing that, then? – Justin L. Apr 29 '13 at 08:14
  • thank you for your advice, i think i have something running :) Do you mind elaborating on how to determine if something should be a functor or a monad? I'm not sure I understand the theoretical difference. – Justin L. Apr 29 '13 at 08:26
  • @JustinL. It might help to read [this answer](http://stackoverflow.com/questions/13134825/how-do-functors-work-in-haskell/13137359#13137359) where I accidently wrote a functors tutorial. Rough rule of thumb: a functor has/contains/produces a value/values that you can apply a function to, whereas a monad is usually some sort of computation that produces a value/values. (So a monad is a funtor because it produces values, but not all functors _do_ anything as such, and some cannot be made into a monad.) – AndrewC Apr 29 '13 at 10:50

1 Answers1

7

In terms of syntax, it's

instance Monad (DataPoint x) where
    -- etc

Although I share hammar's concerns and think you should be trying to make it a Functor instead:

instance Functor (DataPoint x) where
    -- etc

The kind error you get

The first argument of `Monad' should have kind `* -> *',
but `DataPoint x dataval' has kind `*'

is because Monad and Functor are typeclasses that apply to higher order types (compare with Monoid, a typeclass that applies to simple types).

e.g. IO Int is not a monad; IO () is not a monad; IO is a monad.


I want a type DataPoint, which stores either a tuple (x, dataval) or two fields x and dataval (where x is a Double and dataval is a Complex Double.

data DataPoint a = DataPoint {x :: Double,
                              dataval :: a}

instance Functor DataPoint where
    fmap f dataPoint = DataPoint {x = x dataPoint,
                                  dataval = f (dataval dataPoint)}
Ilya Rezvov
  • 914
  • 5
  • 13
dave4420
  • 46,404
  • 6
  • 118
  • 152
  • Thanks, I think I have it running :) Do you mind elaborating on the differences between functors and monads? I'm trying to figure it out still. – Justin L. Apr 29 '13 at 08:27
  • 2
    Functors and Monads are different typeclasses. Read the first few chapters of [the Typeclassopedia](http://www.haskell.org/haskellwiki/Typeclassopedia) if you've not done so yet. – dave4420 Apr 29 '13 at 08:30
  • Thank you @ИльяРезвов for the edit. Everyone else: this is why you should use `{-# LANGUAGE DeriveFunctor #-}` and `deriving Functor`: it reduces the amount of code you can make silly mistakes in. – dave4420 Apr 29 '13 at 17:21