Вопрос

I have a function

sasiad (x,y) = [ (x+dx,y+dy) | dy <- [-1..1], dx <- [-1..1], x+dx >= 0, y+dy >= 0]

I don't like the type of that function. I would like it to return [(Int,Int)] instead of [(t,t1)] Is it possible to force ghci to make that?

Это было полезно?

Решение

Yes, add a type annotation:

sasiad (x,y) = [ (x+dx,y+dy) | dy <- [-1..1], dx <- [-1..1], x+dx >= 0, y+dy >= 0] :: [(Int, Int)]

Другие советы

You can add a type annotation as dave4420 mentions, but the normal way of doing so is this:

sasiad :: (Int, Int) -> [(Int, Int)]
sasiad (x,y) = [ (x+dx,y+dy) | dy <- [-1..1], dx <- [-1..1], x+dx >= 0, y+dy >= 0]

There is, however, an argument to be made for using the type that the compiler infers:

sasiad :: (Ord t1, Ord t, Num t1, Num t, Enum t, Enum t1) => (t, t1) -> [(t, t1)]

As this blog entry argues, the more complex type has advantages. For example, the fact that the inferred type for your function distinguishes between t and t1 means that if you declare this type, the compiler won't let you mix up the arguments; basically, this type guarantees that the first elements of the pairs in the result list are computed using x only, and the second elements are computed using y only. Whether this is an useful invariant depends on your program.

Also, I can't help but to refactor your function:

sasiad :: (Ord t1, Ord t, Num t1, Num t, Enum t, Enum t1) => (t, t1) -> [(t, t1)]
sasiad (x,y) = cross (generate x) (generate y)
    where generate x = filter (>=0) . map (\dx -> x+dx) $ [-1..1]

cross xs ys = [ (x,y) | x <- xs, y <- ys ]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top