엄격한 실존 유형을 정의하는 방법은 무엇입니까?

크리스

엄격한 컨텍스트에서 Haskell의 존재 유형 ( http://www.haskell.org/haskellwiki/Existential_type ) 을 사용하고 싶습니다 . 저는 haskell-wiki에서 예제를 가져 와서 엄격한 이기종지도를 만들려고했습니다. 지도와 그 값이 완전히 평가되어야합니다.

이것을 테스트하기 위해 세 가지 유형을 정의했습니다. 첫 번째는 단순한 엄격한지도입니다. 두 번째 유형은 실존 유형을 사용하는 이기종 맵입니다. 세 번째 유형은 두 번째 유형과 비슷하지만 NFData 제약 조건을 추가합니다.

첫 번째 간단한 예제는 진정으로 엄격하고 완전히 평가되지만 다른 예제는 그렇지 않습니다. deepseq를 사용하는 세 번째 유형조차도 완전히 평가되지 않은 것 같습니다.

내 질문은 다음과 같습니다.

  • 이러한 이기종 유형을 엄격한 방식으로 어떻게 정의합니까?
  • 가능하지 않다면-왜 안되죠? 이 문제를 해결할 방법이 있습니까?

예제 소스

{-# LANGUAGE ExistentialQuantification #-}

import GHC.AssertNF
import Control.DeepSeq
import Data.Map.Strict

-- 1) simple container

data Obj a = Obj a

-- using a smart constructor here to ensure arbitrary values are strict
mkObj :: a -> Obj a
mkObj a = Obj $! a

-- using a special String constructor to ensure Strings are always 
-- fully evaluated in this example
mkString :: String -> String
mkString x = force x

xs :: Map Int (Obj String)
xs = fromList [ (1, mkObj . mkString $ "abc")
              , (2, mkObj . mkString $ "def")
              , (3, mkObj . mkString $ "hij")
              ]

-- 2) container using existential quantification

data Obj2 = forall a. (Show a) => Obj2 a

-- using the smart constructor here has no effect on strictness
mkObj2 :: Show a => a -> Obj2
mkObj2 a = Obj2 $! a

xs2 :: Map Int Obj2
xs2 = fromList [ (1, mkObj2 1)
               , (2, mkObj2 . mkString $ "test")
               , (3, mkObj2 'c')
               ]

-- 3) container using existential quantification and deepseq

data Obj3 = forall a. (NFData a, Show a) => Obj3 !a

instance NFData Obj3 where
  -- use default implementation

mkObj3 :: (NFData a, Show a) => a -> Obj3
mkObj3 a = Obj3 $!! a

xs3 :: Map Int Obj3
xs3 = fromList [ (1, mkObj3 (1::Int))
               , (2, mkObj3 . mkString $ "abc")
               , (3, mkObj3 ('c'::Char))
               ]

-- strictness tests
main :: IO ()
main = do
  putStr "test: simple container: "
  (isNF $! xs) >>= putStrLn . show
  assertNF $! xs
  putStr "test: heterogeneous container: "
  (isNF $! xs2) >>= putStrLn . show
  assertNF $! xs2
  putStr "test: heterogeneous container with NFData: " 
  (isNF $!! xs3) >>= putStrLn . show
  assertNF $!! xs3 
  return ()

GHCI 출력

test: simple container: True
test: heterogeneous container: False
Parameter not in normal form: 1 thunks found:
let x1 = Tip()
in Bin (I# 2) (Obj2 (_sel (_bh (...,...))) (C# 't' : C# 'e' : ... : ...)) (Bin (I# 1) (Obj2 (D:Show _fun _fun _fun) (S# 1)) x1 x1 1) (Bin (I# 3) (Obj2 (D:Show _fun _fun _fun) (C# 'c')) x1 x1 1) 3
test: heterogeneous container with NFData: False
Parameter not in normal form: 1 thunks found:
let x1 = _ind ...
    x2 = Tip()
in _bh (Bin (I# 2) (Obj3 (_bh (_fun x1)) (_sel (_bh (...,...))) (C# 'a' : C# 'b' : ... : ...)) (Bin (I# 1) (Obj3 (_ind _fun) (D:Show _fun _fun _fun) (I# 1)) x2 x2 1) (Bin (I# 3) (Obj3 x1 (D:Show _fun _fun _fun) (C# 'c')) x2 x2 1) 3)
좌회전

믿거 나 말거나, 세 가지 테스트 모두 엄격합니다! 의미에서 저장하는 "이종 객체"는 컨테이너 객체에 넣기 전에 평가됩니다.

엄격하지 않은 것은 실존 적 구현 일뿐입니다. 문제는 Haskell이 실제로 실존성을 가지고 있지 않으며 유형 클래스 사전을 저장하는 레코드 유형에 의해 에뮬레이션된다는 것입니다. Show제약 조건의 경우 기본적으로 객체를 저장하지 않고 show문자열 인의 결과 만 저장한다는 의미 입니다. 그러나 GHC는 문자열이 엄격하게 평가 되기를 바라는 것을 알 수 없습니다 . 사실 그것은 show일반적으로 객체를 심층 평가하는 것보다 훨씬 더 비쌀 수 있기 때문에 일반적으로 나쁜 생각 입니다. 그래서 show당신이 그것을 부를 때 평가 되어야만합니다. 이것은 아주 좋은 IMO입니다.

show엄격하게 평가하려는 경우 확인하는 유일한 방법은 레코드 변환을 명시 적으로 만드는 것입니다. 귀하의 예에서는 사소한 것입니다.

newtype Obj2 = Obj2 { showObj2 :: String }
mkObj2 :: Show a => a -> Obj2
mkObj2 = (Obj2 $!) . show

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

각도의 다른 변수를 사용하여 엄격한 데이터 유형 변수 값을 할당하는 방법은 무엇입니까?

분류에서Dev

매개 변수없이 301 엄격한 URL을 리디렉션하는 방법은 무엇입니까?

분류에서Dev

하위 유형으로 캐스팅하기위한 몇 가지 엄격한 "규칙"은 무엇입니까?

분류에서Dev

기존 객체 값을 기반으로 Typescript 객체 유형을 정의하는 방법은 무엇입니까?

분류에서Dev

존재하는 코드가 모호한 기능을 재정의하는 방법은 무엇입니까?

분류에서Dev

OpenSSH-엄격한 호스트 키 검사를 유지하지만 키만 확인하고 서버 이름을 무시하는 방법은 무엇입니까?

분류에서Dev

템플릿 메서드에 대한 자동 유형 변환을 실현하는 방법은 무엇입니까?

분류에서Dev

상수에 대한 유형을 지정하는 방법은 무엇입니까?

분류에서Dev

Android MotionLayout / MotionScene에 정의 된 애니메이션을 무한히 실행하는 방법은 무엇입니까?

분류에서Dev

Perl에서 $ a에 대해 엄격한 pragma가 실패하는 이유는 무엇입니까?

분류에서Dev

이 str 엄격한 비교가 Python에서 실패하는 이유는 무엇입니까?

분류에서Dev

이러한 유형의 문자열을 정렬하는 가장 좋은 방법은 무엇입니까?

분류에서Dev

기존 실행기 항목에 대한 명령을 얻는 방법은 무엇입니까?

분류에서Dev

'std :: function'의 유형이 전적으로 호출 서명에만 의존한다는 것을 이해하는 방법은 무엇입니까?

분류에서Dev

의존성 의존성 유형을 사용하는 방법은 무엇입니까?

분류에서Dev

실행 유형의 이름을 얻는 방법은 무엇입니까?

분류에서Dev

@ObservedObject 속성에 대한 유형으로 프로토콜을 정의하는 방법은 무엇입니까?

분류에서Dev

MS Graph : 로그인 한 사용자의 계정 유형을 확인하는 방법은 무엇입니까?

분류에서Dev

생존 플롯에서 사용자 지정 x 축 간격을 설정하는 방법은 무엇입니까?

분류에서Dev

데이터 유형 및 공동 데이터 유형에 대한 기본 사실을 증명하는 방법은 무엇입니까?

분류에서Dev

프롤로그에서 고유 한 사실을 지정하는 방법은 무엇입니까?

분류에서Dev

"구조물 상속"이 엄격한 앨리어싱 규칙을 위반하지 않는 방법은 무엇입니까?

분류에서Dev

긍정적 이성에 대한 반감 기능이 항상 실존적임을 증명하는 방법은 무엇입니까?

분류에서Dev

원격 PC에서 htop을 실행하는 방법은 무엇입니까?

분류에서Dev

격일로 cronjob을 실행하는 방법은 무엇입니까?

분류에서Dev

stable () 실행 후 나무 간격을 줄이는 방법은 무엇입니까?

분류에서Dev

libxml2가 엄격하지 않은 HTML을 구문 분석하는 방법은 무엇입니까?

분류에서Dev

Google 크롬을 두 개의 고유 한 Google 크롬으로 실행하는 방법은 무엇입니까?

분류에서Dev

린에서 Pi 유형을 사용하여 비의존 제품의 정의를 작성하는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    각도의 다른 변수를 사용하여 엄격한 데이터 유형 변수 값을 할당하는 방법은 무엇입니까?

  2. 2

    매개 변수없이 301 엄격한 URL을 리디렉션하는 방법은 무엇입니까?

  3. 3

    하위 유형으로 캐스팅하기위한 몇 가지 엄격한 "규칙"은 무엇입니까?

  4. 4

    기존 객체 값을 기반으로 Typescript 객체 유형을 정의하는 방법은 무엇입니까?

  5. 5

    존재하는 코드가 모호한 기능을 재정의하는 방법은 무엇입니까?

  6. 6

    OpenSSH-엄격한 호스트 키 검사를 유지하지만 키만 확인하고 서버 이름을 무시하는 방법은 무엇입니까?

  7. 7

    템플릿 메서드에 대한 자동 유형 변환을 실현하는 방법은 무엇입니까?

  8. 8

    상수에 대한 유형을 지정하는 방법은 무엇입니까?

  9. 9

    Android MotionLayout / MotionScene에 정의 된 애니메이션을 무한히 실행하는 방법은 무엇입니까?

  10. 10

    Perl에서 $ a에 대해 엄격한 pragma가 실패하는 이유는 무엇입니까?

  11. 11

    이 str 엄격한 비교가 Python에서 실패하는 이유는 무엇입니까?

  12. 12

    이러한 유형의 문자열을 정렬하는 가장 좋은 방법은 무엇입니까?

  13. 13

    기존 실행기 항목에 대한 명령을 얻는 방법은 무엇입니까?

  14. 14

    'std :: function'의 유형이 전적으로 호출 서명에만 의존한다는 것을 이해하는 방법은 무엇입니까?

  15. 15

    의존성 의존성 유형을 사용하는 방법은 무엇입니까?

  16. 16

    실행 유형의 이름을 얻는 방법은 무엇입니까?

  17. 17

    @ObservedObject 속성에 대한 유형으로 프로토콜을 정의하는 방법은 무엇입니까?

  18. 18

    MS Graph : 로그인 한 사용자의 계정 유형을 확인하는 방법은 무엇입니까?

  19. 19

    생존 플롯에서 사용자 지정 x 축 간격을 설정하는 방법은 무엇입니까?

  20. 20

    데이터 유형 및 공동 데이터 유형에 대한 기본 사실을 증명하는 방법은 무엇입니까?

  21. 21

    프롤로그에서 고유 한 사실을 지정하는 방법은 무엇입니까?

  22. 22

    "구조물 상속"이 엄격한 앨리어싱 규칙을 위반하지 않는 방법은 무엇입니까?

  23. 23

    긍정적 이성에 대한 반감 기능이 항상 실존적임을 증명하는 방법은 무엇입니까?

  24. 24

    원격 PC에서 htop을 실행하는 방법은 무엇입니까?

  25. 25

    격일로 cronjob을 실행하는 방법은 무엇입니까?

  26. 26

    stable () 실행 후 나무 간격을 줄이는 방법은 무엇입니까?

  27. 27

    libxml2가 엄격하지 않은 HTML을 구문 분석하는 방법은 무엇입니까?

  28. 28

    Google 크롬을 두 개의 고유 한 Google 크롬으로 실행하는 방법은 무엇입니까?

  29. 29

    린에서 Pi 유형을 사용하여 비의존 제품의 정의를 작성하는 방법은 무엇입니까?

뜨겁다태그

보관