How to declare type of this function?

*爱你&永不变心* 提交于 2019-12-13 00:32:32

问题


I'm using vector library and trying to write simple function:

import qualified Data.Vector.Generic as GV

setCharges :: GV.Vector v Double => 
              Network -> v Double -> Network
setCharges n cs = n{nodes = GV.zipWith setCharge (nodes n) cs}

With XFlexibleContexts ghc accepts type declaration but complain near cs varibale

Could not deduce (v ~ Vector)

I have

nodes n :: Data.Vector.Vector Node
setCharge :: Node -> Double -> Node

Don't really get, what the problem.


回答1:


It's just what GHC says: the setCharges signature only requires that v is some instance of the class Data.Vector.Generic.Vector. The nodes field of Network, OTOH, is always one particular type, namely Data.Vector.Vector, which sure enough is an instance of the Vector class, but there can be others as well. So you can't just replace this field with some other type, no matter if it's an instance of GV.Vector or not. But there's a generic function to convert between such instances, use that and you'll be fine:

setCharges n cs = n{nodes = GV.zipWith setCharge (nodes n) (GV.convert cs)}

Alternatively, you could design the Network record so the nodes field is in fact polymorphic, i.e. can hold arbitrary instances of the class rather than one particular type. This is called an existential:

{-# LANGUAGE ExistentialQuantification       #-}

data Network = Network { ...
                       , nodes :: forall v . GV.Vector v => v Double
                       , ...
                       }

But it's generally considered a bit of an antipattern, at least if there isn't a particular reason to go this route.



来源:https://stackoverflow.com/questions/18141442/how-to-declare-type-of-this-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!