简体   繁体   中英

weird type issue in haskell giving me issues (Par Monad)

For reference my code.

import Control.Monad.Par

makeGridx:: (Enum a,Num a)=>a->a->a->[a]
makeGridx start end h = [start,(start+h)..end]
makeGridt:: (Enum a, Num a)=>a->a->a->[a]
makeGridt start end h = [start,(start+h)..end]

generateBaseLine:: (Eq a,Num a)=>(a->a)-> [a] -> [(a,a,a)]
generateBaseLine f (x:xs) = if (null xs)
                            then [(x,0,0)]
                            else if(x==0)
                                then (x,0,0) : (generateBaseLine f xs)
                                else (x,0,(f x)) : (generateBaseLine f xs)

--fdm :: (Enum a,Num a) =>a->a->a->a->a->a->a->(a->a)->[(a,a,a)]
--fdm alpha startt endt startx endx dx dt bbFunction = start alpha (makeGridx startx endx dx) (makeGridt startt endt dt) (generateBaseLine bbFunction (makeGridx startx endx dx)) dx dt

--start:: Num a=>a->[a]->[a]->[(a,a,a)]->a->a->[(a,a,a)]
--start alpha (x:xs) (t:ts) (phi:phis) dx dt =  (startPar alpha (x:xs) (ts) (phi:phis) dx dt [] [])

startPar:: Num a =>a->[a]->[a]->[(a,a,a)]->a->a->[(a,a,a)]
startPar alpha (x:xs) (t:ts) (phi1:(ph2:(ph3:phis))) dx dt = (phi1:(ph2:(ph3:phis))) ++ (buildPhiListIds alpha (x:xs) (t:ts) (phi1:(ph2:(ph3:phis))) dx dt [] [])
buildPhiListIds:: Num a=> a->[a]->[a]->[(a,a,a)]->a->a->[Par (IVar (a, a, a))]->[a]->[(a,a,a)]                                                              
buildPhiListIds alpha (x:xs) (t:ts) (phi1:(ph2:(ph3:phis))) dx dt phiIds newX = do 
                                                                        one<-third phi1
                                                                        two<-third ph2
                                                                        three<-third ph3
                                                                        newSolId<- spawn( return (newPhi (x:xs) t (one,two,three,dx,dt,alpha) ))
                                                                        buildPhiListIds alpha xs (t:ts) (ph2:(ph3:phis)) dx dt (phiIds ++ [newSolId]) (newX ++ [x])

buildPhiListIds alpha (0:xs) (t:ts) (phi1:(ph2:(ph3:phis))) dx dt phiIds newX = do 
                                                                        newSolId<-spawn (return (newPhi (0:xs) t (1,2,3,4,5,6)))            
                                                                        buildPhiListIds alpha xs (t:ts) (phi1:(ph2:(ph3:phis))) dx dt (phiIds ++ [newSolId]) (newX ++ [0])

buildPhiListIds alpha [] (t:ts) (phi1:(ph2:(ph3:phis))) dx dt phiIds newX = do
                                                                            (getSolutions (getTuples(getSolutions phiIds))) ++ (buildPhiListIds alpha newX  ts (getSolutions (getTuples(getSolutions phiIds)))  dx dt [] []) 

buildPhiListIds _ _ [] _ _ _ _ _ = []


getTuples::[IVar a]->[Par a]
getTuples (x:xs) = (get x) : (getSolutions xs)
getTuples [] = []  

getSolutions:: [Par a]->[a]
getSolutions (x:xs) = (runPar x):(getTuples xs)
getSolutions [] = []


third (_,_,x)=x

ex f g x = runPar $ do
      fx <- spawn (return (f x))  
      gx <- spawn (return (g x))  
      a <- get fx       
      b <- get gx       
      return (a,b)      
newPhi:: (Eq a,Fractional a)=> [a]->a->(a,a,a,a,a,a)->(a,a,a)
newPhi (0:xs) t (phiL,phiC,phiR,dx,dt,alpha)= (0,t,0)
newPhi (x:[]) t (phiL,phiC,phiR,dx,dt,alpha)= (x,t,0)
newPhi (x:xs) t (phiL,phiC,phiR,dx,dt,alpha)= (x,t,(phiC + (alpha * (dt/(dx^2)))*(phiR -(2*phiC) + phiL)))

I get a bunch of errors, but one very much complexes me.

heateqpar.hs:28:156:
    Couldn't match type `Par' with `[]'
    Expected type: [IVar (a1, a1, a1)]
      Actual type: Par (IVar (a1, a1, a1))
    In a stmt of a 'do' block:
      newSolId <- spawn
                    (return (newPhi (x : xs) t (one, two, three, dx, dt, alpha))) ::
                    Par (IVar (a, a, a))
    In the expression:
      do { one <- third phi1;
           two <- third ph2;
           three <- third ph3;
           newSolId <- spawn
                         (return (newPhi (x : xs) t (one, two, three, dx, dt, alpha))) ::
                         Par (IVar (a, a, a));
           .... }
    In an equation for `buildPhiListIds':
        buildPhiListIds
          alpha
          (x : xs)
          (t : ts)
          (phi1 : (ph2 : (ph3 : phis)))
          dx
          dt
          phiIds
          newX
          = do { one <- third phi1;
                 two <- third ph2;
                 three <- third ph3;
                 .... }

The actual type of this is what i want it to be, but for some reason it is trying to enforce this type that isnt the return type of spawn? When i see this it seems like in my type declaration is trying to enforce this however i have the type as followed

buildPhiListIds:: Num a=> a->[a]->[a]->[(a,a,a)]->a->a->[Par (IVar (a, a, a))]->[a]->[(a,a,a)]  

I see no type specifically of [IVar (a1, a1, a1)], which is really confusing me. If someone could lead me on the right road, it would be very much appreciated.

I get a bunch of errors, but one very much complexes me.

In a do expression, every monadic action must belong to the same monad. The return type of buildPhiListIds is [something] , so the result of do has type [something] . Therefore, all your actions should be in the list monad, not in the Par monad. Now look at spawn again:

spawn :: NFData a => Par a -> Par (IVar a)

Compare what I mentioned above with your error: "Couldn't match type `Par' with `[]'". Aha! It expects a list , but you're using something of wrong type ( Par )!

Now, extrapolating from your previous questions I suppose that you're new to Haskell and the concept of monads. There are many tutorials about them, including chapters in RWH or in LYAH , so I won't provide one in this answer (they're actually rather easy, don't be intimidated by the number of tutorials). Either way, your current usage is completely off.

That being said, you should refactor buildPhiListIds to have the following type:

buildPhiListIds:: Num a => ... -> Par [(a,a,a)]

Also, your definitions of getTuples and getSolutions don't make much sense. The following are much simpler and probably achieve what you actually want:

getTuples :: [IVar a] -> [Par a]
getTuples = map get

getSolutions :: [Par a] -> [a]
getSolutions = runPar . sequence 

Also, you should try to keep the calls to runPar to a minimum:

The runPar function itself is relatively expensive [...]. So when using the Par monad, you should usually try to thread the Par monad around to all the places that need parallelism to avoid needing multiple runPar calls. [...] In particular, nested calls to runPar (where a runPar is evaluated during the course of executing another Par computation) usually give poor results.

I suggest you to write some simpler programs which actually compile, till you get both monads in general and Par .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM