0

Hey Everyone I am trying to make Neuron as an Object that is a list of 3 doubles after declaration, however when I try to write the recall method, it says • Couldn't match expected type ‘[Double]’ with actual type ‘Neuron’, anyone knows where the problem is thanks in advance

-- simple neuron
data Neuron = Neuron [Double]
      deriving (Read,Show)

recall :: Neuron -> [Double] -> Double
recall ws xs = y
 where y = sum (zipWith (*) ws (-1:xs))
7
  • 7
    Your Neuron is not a list, it contains a list. Try recall (Neuron ws) xs = ... Commented Oct 22, 2020 at 22:50
  • If it should be 3 doubles (no more, and no less) you probably should use tuple (Double, Double, Double) Commented Oct 23, 2020 at 11:36
  • 1
    @user28434 actually then it should be data Neuron = Neuron !Double !Double !Double, probably. But, why would it be always exactly 3? Commented Oct 23, 2020 at 11:54
  • 1
    @AndrewRay if anything, it should be a newtype around something like V3. Commented Oct 23, 2020 at 12:48
  • 1
    @leftaroundabout Potentially, but some people are less comfortable introducing external dependencies and I don't want to assume people want to use external packages without them being mentioned. And ultimately, this is tangential to OP's question. Commented Oct 23, 2020 at 12:51

1 Answer 1

2

Neuron is not the same thing as [Double]; it is instead a wrapper around [Double]. Thus you must unwrap the value before you can use it like a list:

recall :: Neuron -> [Double] -> Double
recall (Neuron ws) xs = y
    where y = sum (zipWith (*) ws (-1:xs))

Though I have another issue with your code. In this example, since you know that a Neuron must wrap a list of specifically 3 Doubles, you should enforce that with the type system, instead defining Neuron as:

newtype Neuron = Neuron (Double, Double, Double)
    deriving (Read, Show)

recall :: Neuron -> [Double] -> Double
recall (Neuron (w1, w2, w3)) xs = y (xs ++ repeat 0)
    where y (x2:x3:_) = w1 * (-1) + w2 * x2 + w3 * x3

Yes, you lose out on using zipWith and sum, but that's really just obscuring a simpler underlying calculation. There's no need to use generic functions when only one specific case will ever be used.

Note also the use of newtype instead of data. newtype gives you potentially more performant derived implementations of Read and Show and also provides access to advanced tools like Generalized Newtype Deriving, which you may not care about now, but later may be very useful. In general, using newtype instead of data for datatypes that just wrap another datatype is a good habit to get into.

In a comment, @leftroundabout also mentions that if the data do not naturally form a tuple or vector, you should not wrap a tuple, in which case the code would look like this:

data Neuron = Neuron { property1 :: Double
                     , property2 :: Double
                     , property3 :: Double
                     } deriving (Read, Show)

recall :: Neuron -> [Double] -> Double
recall (Neuron w1 w2 w3) xs = y (xs ++ repeat 0)
    where y (x2:x3:_) = w1 * (-1) + w2 * x2 + w3 * x3
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.