Winssen
Winssen

Reputation: 63

Haskell Infinite loop in a recursive function

I am beginner to Haskell Im trying to make neuron to do that I need to generate random numbers for the weights of neurones but I'm stuck at function random it provokes an infinite loop I can't figure where the problem is, in addition when I ask in terminal when compiled take 3 random it always give me the same numbers I want it to take different random numbers each time

l = [1,0,1,1,0,0,1,0]

toDec :: [Int] -> Float
toDec []     = 0
toDec (x:xs) = fromIntegral  x+2*(toDec xs)

next :: [Int] -> [Int]
next xs = xs'
 where xs' = v:(init xs)
       v   = xor (last xs) (xs!!4)

random :: [Float]
random = ran l
       where ran l = ( (toDec l) /  255.0):(ran (next l))

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

n = Neuron (take 3 random)

Upvotes: 2

Views: 481

Answers (1)

leftaroundabout
leftaroundabout

Reputation: 120711

You function works perfectly fine: it generates an infinite list of pseudorandom numbers.

(It's not a particularly good PRNG – for serious applications you should better use a library, random-fu is very extensive – but for educational purposes it's fine.)

But well, you need to be clear what this actually means. Because random is just a value of type [Float], it of course is always the same list. You can still use it for obtaining multiple different finite lists, by splitting up the single infinite one:

n₀, n₁, n₂ :: Neuron
(n₀:n₁:n₂:_) = Neuron <$> splits 3 random

-- | @splits n l@ gives a list of sublists of @l@, each of which has length @n@.
--   If the sublists are concatenated again, you get back @l@.
splits :: Int -> [a] -> [[a]]
splits nPerList l = case splitAt nPerList l of
   (h,[]) -> [h]
   (h,t) -> h : splits nPerList t

If you want something that behaves like the “random functions” in imperative languages, i.e. something that gives a different value each time it's called... well that's not a function then, because a function must for given input yield always the same result. However you can implement it as an action in a suitable monad. In an imperative language, there would be an implicit state of the PRNG. You can have that in Haskell too, except the state is explicit (which actually has a lot of advantages for reliability).

import Control.Monad.Trans.State

type RandSupply = State [Float]

oneRandom :: RandSupply Float
oneRandom = do
  ~(h:t) <- get   -- This is a bit of a hack†
  put t
  return h

randomNeuron :: Int -> RandSupply Neuron
randomNeuron nWeights = Neuron <$> replicateM nWeights oneRandom

Then you can write code like

import Control.Monad

     (`evalState`random) $ do
         ...
         n <- randomNeuron 3
         ...
         n₅ <- randomNeuron 5
         ...

and n and n₅ will have different weights, because the state of the supply-list has changed in between.


The irrefutable match ~(h:t) means that the action can fail badly if you try to use it with only a finite supply of random numbers. Again: the proper thing to do is to use a library for random numbers, rather than rolling your own.

Upvotes: 2

Related Questions