在haskell中返回不同的类型

时间:2013-10-30 05:01:49

标签: haskell types

我对Haskell有点新,我正在开发一个项目,我有以下代码:

data Nested a = Elem a | Nested [Nested a] deriving (Eq, Show)
data Symbol a = Value a | Transformation (a -> a -> a) deriving (Show)


toSymbol :: [Char] -> Nested (Symbol Integer)
toSymbol x  
|all isDigit x = Elem (Value (strToInt x))
|x == "+" = Elem (Transformation (\x y -> x + y))

有没有办法可以避免将此函数的类型限制为嵌套(符号整数)?我想使用Symbol来表示许多不同的类型,并且具有以下几行的符号功能:

toSymbol x  
|x == "1" = Elem (Value 1)
|x == "+" = Elem (Transformation (\x y -> x + y))
|x == "exampleword" = Elem (Value "word")
|x == "concatenate()" = Elem (Transformation concatTwoStrings)

我不知道像这样的函数的类型签名是什么。我有什么办法可以获得类似的功能吗?

2 个答案:

答案 0 :(得分:3)

我认为不可能编写单个函数来执行此操作。一种可能的解决方案是使用类型类,它保留单个函数API:

{-# LANGUAGE FlexibleInstances #-}

...

class Token a where
    toSymbol :: String -> Nested a

instance Token (Symbol Integer) where
    toSymbol x
        |all isDigit x = Elem (Value (read x))
        |x == "+" = Elem (Transformation (\x y -> x + y))
        |otherwise = error "Wrong type"

instance Token (Symbol String) where
    toSymbol "exampleword" = Elem (Value "word")
    toSymbol "concatenate()" = Elem (Transformation (++))
    toSymbol _ = error "Wrong type"

答案 1 :(得分:3)

您无法弄清楚类型签名的原因是因为您正在尝试执行此操作“使函数的返回类型取决于传递的字符串的值,也就是依赖类型编程”,该值的值string仅在运行时可用。

所以基本上如果你试着说:toSymbol :: String -> Nested (Symbol a)a取决于字符串的运行时值,以及编译器抱怨它的原因。

有许多方法可以优化你的类型,以便所有部分都适合在一起,一种可能的解决方案是使用一种新类型,它指定符号可能具有的不同类型的值。以下是示例:

data Nested a = Elem a | Nested [Nested a] deriving (Eq, Show)
data Symbol a = Value a | Transformation (a -> a -> a)
data SymbolType = SInteger Integer | SString String

addSymbols :: SymbolType -> SymbolType -> SymbolType
addSymbols (SInteger a) (SInteger b) = SInteger (a+b)
addSymbols _ _ = error "Not possible"

concatSymbols :: SymbolType -> SymbolType -> SymbolType
concatSymbols (SString a) (SString b) = SString (a++b)
concatSymbols _ _ = error "Not possible"

toSymbol :: String -> Nested (Symbol SymbolType)
toSymbol x  
  |x == "1" = Elem (Value (SInteger 1))
  |x == "+" = Elem (Transformation addSymbols)
  |x == "exampleword" = Elem (Value (SString "word"))
  |x == "concatenate()" = Elem (Transformation concatSymbols)
相关问题