Where를 사용하여 중첩 된 기능 정의에서 Haskell Scoping
-
10-07-2019 - |
문제
Haskell의 범위에 문제가 있습니다 where
정의. 다음 기능이있을 때 f
, 내가 전달하고 싶은 곳 x
로컬로 정의 된 함수에 f1
매개 변수로 설명하지 않고 x
출력의 하나와 호환되지 않습니다 f1
, 동일하지만 :
f :: Eq a => a -> [a] f x = f1 x where f1 :: Eq a => a -> [a] f1 y = [ x, y ]
오류는 다음과 같습니다.
Couldn't match expected type `a1' against inferred type `a' `a1' is a rigid type variable bound by the type signature for `f1' at test.hs:4:11 `a' is a rigid type variable bound by the type signature for `f' at test.hs:1:8 In the expression: x In the expression: [x, y] In the definition of `f1': f1 y = [x, y] Failed, modules loaded: none.
그러나 내가 통과 할 때 x
기능과 함께 다음 코드에서했던 것처럼 추가 매개 변수로 g
, 그것은 잘 작동합니다 :
g :: Eq a => a -> [a] g x = g1 x x where g1 :: Eq a => a -> a -> [a] g1 x y = [ x, y ]
유형을 만드는 방법이 있습니까? a
안에 f
유형과 호환됩니다 a
(또는 a1
) 안에 f1
?
해결책
코드의 문제는 로컬 스코핑 된 F1 유형 서명입니다. F1이 모든 유형을 취할 수 있음을 지정합니다
f1 :: Eq a => a -> [a]
이것은 로컬 기능이지만,이 함수는 F 내에 존재하지 않는 유형을 취할 수 있도록이 기능을 일반화했습니다.
F1 유형 서명을 제거하십시오.
편집 : 내 게시물을 나 자신에게 다시 읽으십시오. 조금 불분명합니다. F1의 A는 무엇이든 할 수있는 매개 변수화 유형이지만, 전달 된 인수는 이미 f에 묶여 있습니다. 따라서이 기능은 부모 기능이받는 것만받을 수 있으며, 그 규칙을 깨뜨리는 유형 서명입니다. 조금 더 분명하기를 바랍니다.
다른 팁
데이브가 바로 위에 있습니다. 그것을 생각하는 또 다른 방법은 두 유형 서명이 변수를 참조하더라도 a
, 실제로는 같은 유형 변수가 아닙니다. Haskell-Prime 표기법에서 두 서명 모두보다 명시 적으로 작성 될 수 있습니다.
forall a . Eq a => a -> [a]
그것을 의미합니다 둘 다 함수는 어떤 유형의 인수를 받아 들일 수 있습니다 (EQ 내에서). 이것은 분명히 여기에 해당되지 않습니다. Standard Haskell 98에서 유일한 옵션은 유형 서명을 포기하는 것입니다. f1
. 그러나 GHC (및 기타?) 지원 어휘 스코핑 유형 변수. 그래서 당신은 쓸 수 있습니다
{-# LANGUAGE ScopedTypeVariables #-}
f :: forall a. Eq a => a -> [a]
f x = f1 x
where
f1 :: a -> [a]
f1 y = [ x, y ]
그리고 그것은 잘 작동합니다.